C # Преобразование функции криптографии XOR - PullRequest
1 голос
/ 27 января 2011

Я работал над преобразованием метода шифрования C ++ в C #. Проблема в том, что я не могу заставить его шифровать / дешифровать так, как я хочу.

Идея проста: я собираю пакет и дешифрую его. Выход будет: Размер пакета - Команда / Действие - Ноль (Конец)

(расшифровщик обрезает первые и последние 2 байта)

Код C ++ выглядит так:

// Crypt the packet with Xor operator
void cryptPacket(char *packet)
{
    unsigned short paksize=(*((unsigned short*)&packet[0])) - 2;

    for(int i=2; i<paksize; i++)
    {
         packet[i] = 0x61 ^ packet[i];
    }
}

Поэтому я подумал, что это будет работать в C #, если я не хочу использовать указатели:

public static char[] CryptPacket(char[] packet)
{
    ushort paksize = (ushort) (packet.Length - 2);

    for(int i=2; i<paksize; i++)
    {
        packet[i] = (char) (0x61 ^ packet[i]);
    }

    return packet;
}

- но это не так, возвращаемое значение является просто еще одной строкой разметки вместо расшифрованного значения. Выходные данные: ..O ♦ & / OOOe.

Ну, по крайней мере, "/" по какой-то причине находится в правильном месте.

Дополнительная информация:

  • Используемый мной тестовый пакет:

шестнадцатеричное значение: 0C 00 E2 66 65 47 4E 09 04 13 65 00

Обычный текст: ... feGN ... e.

Расшифровано: XX / здесьXX

X = Неизвестное значение, я не могу вспомнить, но это не имеет значения.

  • Используя Hex Workshop, вы можете расшифровать пакет следующим образом:
    1. Специально Вставьте шестнадцатеричное значение как CF_TEXT, убедитесь, что флажок «обрабатывать как шестнадцатеричное значение» установлен.
    2. Затем выберите все из шестнадцатеричного значения, которое вы только что вставили, кроме первого и последних 2 байтов.
    3. Выберите Инструменты> Операции> Xor.
    4. Выберите «Обрабатывать данные как 8-битные данные» и установите значение «61».
    5. Нажмите «ОК», и все готово.

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

Спасибо за ваше время.

Если вы не видите в этом вопрос:

Было бы замечательно, если бы кто-то мог взглянуть на код, чтобы увидеть, что с ним не так, или если есть другой способ сделать это. Я конвертирую этот код, потому что я ужасен с C ++ и хочу создать приложение C # с этим кодом.

Ps: теги кода и тому подобное были неприятны, поэтому извините, если интервал и т. Д. Немного испорчены.

Ответы [ 3 ]

2 голосов
/ 27 января 2011

Ваша проблема может заключаться в том, что в качестве символа .NET используется юникод, некоторые символы будут использовать более одного байта, а ваша битовая маска будет иметь длину только один байт. Таким образом, самый значимый байт останется неизменным.

1 голос
/ 27 января 2011

Вот почти буквальный перевод с C ++ на C #, и, похоже, он работает:

var packet = new byte[] {
                            0x0C, 0x00, 0xE2, 0x66, 0x65, 0x47,
                            0x4E, 0x09, 0x04, 0x13, 0x65, 0x00
                        };

CryptPacket(packet);

// displays "....../here." where "." represents an unprintable character
Console.WriteLine(Encoding.ASCII.GetString(packet));

// ...

void CryptPacket(byte[] packet)
{
    int paksize = (packet[0] | (packet[1] << 8)) - 2;

    for (int i = 2; i < paksize; i++)
    {
        packet[i] ^= 0x61;
    }
}
1 голос
/ 27 января 2011

Я только что попробовал вашу функцию, и, кажется, все в порядке:

class Program
{
    // OP's method: http://stackoverflow.com/questions/4815959
    public static byte[] CryptPacket(byte[] packet)
    {
        int paksize = packet.Length - 2;
        for (int i = 2; i < paksize; i++)
        {
            packet[i] = (byte)(0x61 ^ packet[i]);
        }
        return packet;
    }

    // http://stackoverflow.com/questions/321370 :)
    public static byte[] StringToByteArray(string hex)
    {
        return Enumerable.Range(0, hex.Length).
               Where(x => 0 == x % 2).
               Select(x => Convert.ToByte(hex.Substring(x, 2), 16)).
               ToArray();
    }

    static void Main(string[] args)
    {
        string hex = "0C 00 E2 66 65 47 4E 09 04 13 65 00".Replace(" ", "");
        byte[] input = StringToByteArray(hex);
        Console.WriteLine("Input: " + ASCIIEncoding.ASCII.GetString(input));
        byte[] output = CryptPacket(input);
        Console.WriteLine("Output: " + ASCIIEncoding.ASCII.GetString(output));
        Console.ReadLine();
    }
}

Вывод на консоль:

Input: ...feGN.....
Output: ...../here..
(where '.' represents funny ascii characters)

Кажется немного вонючим, что ваш CryptPacket метод перезаписывает исходный массив выходными значениями. И это нерелевантные символы не подстрижены. Но если вы пытаетесь что-то портировать, я думаю, вы должны знать, что вы делаете.

Вы также можете обрезать входной массив, чтобы сначала удалить ненужные символы, а затем использовать общий метод ROT13 (например, этот ). Таким образом, у вас есть собственная «специализированная» версия с 2-байтовыми смещениями внутри самой функции crypt, а не что-то вроде:

public static byte[] CryptPacket(byte[] packet)
{
    // create a new instance
    byte[] output = new byte[packet.Length];

    // process ALL array items
    for (int i = 0; i < packet.Length; i++)
    {
        output[i] = (byte)(0x61 ^ packet[i]);
    }

    return output;
}
...