Функция XOR для двух шестнадцатибайтовых массивов


Я пытаюсь выполнить исключающее ИЛИ двухбайтовых массивов и вернуть результат в виде шестнадцатеричной строки. Я преобразовал двухбайтовый массив в соответствующую двоичную строку. Каждый байт будет иметь биты, так как он имеет 8 байт.

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

До сих пор я использовал метод, который преобразует массив байтов в соответствующее двоичное строковое значение, например "10101010101". Однако когда я выполняю приведенный ниже метод, чтобы получить XOR, я возвращаюсь со строкой связки смайликов, которые вероятно, это какой-то специальный символ ASCII.

Однако у меня нет никаких идей, как я могу это сделать. Я думал преобразовать двоичную строку в целое число, но это не очень хорошее решение, так как оно не будет соответствовать целому числу. У вас есть какие-нибудь идеи, пожалуйста? возможно, с каким-то образцом кода?
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;
}
4 6

4 ответа:

Вы делаете это правильно-ваш код XORs символов двух строк, обернув вокруг второй, если первая из них окажется длиннее.

Однако свойство XOR таково, что в выходных данных остаются только те биты, которые отличаются друг от друга. Следовательно, когда вы XOR 0x11 и 0x12, вы в конечном итоге получаете 0x03, который выглядит как сердце при отображении на консоли.

Попробуйте это:

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();
    }
}

Как это работает: сначала вы проверяете, имеют ли массивы одинаковую длину, и если это так, вы выполняете операцию XOR над массивами. Метод BitConverter.ToString() преобразует массив байтов в строку, но поскольку существуют дефисы для разделения каждого шестнадцатеричного числа, вы можете использовать метод Replace() для удаления этих тире.

Я думаю, что string - это неправильный тип для этого. Вместо этого вы должны использовать BitArray, он даже уже имеет метод Xor().

ИМО было бы лучше разделить это на две части. Одна функция, чтобы сделать кусочно XOR и другая функция, чтобы преобразовать массив байтов в шестнадцатеричную строку.

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();
}

Теперь вы можете просто сказать:

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

Причина, по которой ваше решение печатает странные символы, заключается в том, что вы записываете значения ASCII '1' и '0', поскольку это символы в вашей строке. С '1' это 0x31 и '0' это 0x30, 0x30 0x31 результат операции XOR = 1. Затем вы вводите символ ASCII 0x01 (который является символом непечатаемый управляющий символ) в строку результата.