XOR function for two Hex byte arrays

28,870

Solution 1

You are doing this correctly - your code XORs characters of the two strings, wrapping around the second one if the first one happens to be the longer one.

However, the property of XOR is such that only the bits that are different remain set in the output. Hence, when you XOR 0x11 and 0x12, you end up with 0x03, which looks like a heart when displayed on a console.

Solution 2

Try this:

public static string exclusiveOR(byte[] key, byte[] PAN)
{
    if (key.Length == PAN.Length)
    {
        byte[] result = new byte[key.Length];
        for (int i = 0; i < key.Length; i++)
        {
            result[i] = (byte)(key[i] ^ PAN[i]);
        }
        string hex = BitConverter.ToString(result).Replace("-", "");
        return hex;
    }
    else
    {
        throw new ArgumentException();
    }
}

How this works: first you check whether the arrays have the same length, and if that is the case, you'll perform the XOR operation on the arrays. The BitConverter.ToString() method converts the byte array to a string, but because there are hyphens to seperate each hex number, you can use the Replace() method to remove these dashes.

Solution 3

IMO it would be better to split this into two pieces. One function to do the piecewise XOR and another function to convert the byte array to a hex string.

public static byte[] exclusiveOR(byte[] arr1, byte[] arr2)
{
    if (arr1.Length != arr2.Length)
        throw new ArgumentException("arr1 and arr2 are not the same length");

    byte[] result = new byte[arr1.Length];

    for (int i = 0; i < arr1.Length; ++i)
        result[i] = (byte) (arr1[i] ^ arr2[i]);

    return result;
}

public static string arrayToHexString(byte[] arr)
{
    var sb = new StringBuilder();
    for (int i = 0; i < arr.Length; ++i)
        sb.Append(arr[i].ToString("x2"));
    return sb.ToString();
}

Now you can just say:

Console.WriteLine(arrayToHexString(exclusiveOR(arr1, arr2)));

The reason your solution printed bizarre characters is that you are XORing ASCII values '1' and '0' since those are the characters in your string. Since '1' is 0x31 and '0' is 0x30, the result is 0x30 xor 0x31 = 1. You are then putting ASCII character 0x01 (which is a nonprintable control character) into your result string.

Solution 4

I think string is the wrong type for this. Instead, you should use BitArray, it even already has Xor() method.

Share:
28,870
user2307236
Author by

user2307236

Updated on May 26, 2020

Comments

  • user2307236
    user2307236 almost 4 years

    I am trying to perform the exclusive or of two byte arrays and return the result as a hex string. I have converted the two byte array to their corresponding binary string. Each byte will have bits since it has 8 bytes.

    byte[] key =  { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 };
    byte[] PAN =  { 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23 };
    

    Until now I have used a method that transforms the byte array into their corresponding binary string value, e.g. "10101010101". However when I perform the below method to get the XOR I am being returned with a string of bunch of smiley face which probably is some special ASCII character.

    However I don't have any ideas how I can do this. I was thinking to convert the binary string to an integer, but that is not a good solution since it will not fit as an integer.

    Do you have any ideas, please? possibly with some sample code?

    public static string exclusiveOR(string string_1, string string_2)
    {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < string_1.Length; i++)
            sb.Append((char)(string_1[i] ^ string_2[(i % string_2.Length)]));
            String result = sb.ToString();
    
            return result;
    }