Функция шифрования выдает разные выходные данные в Windows и unix

#c# #.net #encryption #mono #rijndael

#c# #.net #шифрование #mono #rijndael

Вопрос:

У меня есть инструмент шифрования, написанный на C #, который принимает строку в качестве входных данных. Когда я запускаю скомпилированный exe-файл на своем компьютере с Windows, я получаю выходные данные, отличные от тех, которые я получал при запуске на удаленном сервере UNIX с использованием mono.

Вот пример:

Windows:

 "encrypt.exe 01/01"
Output:
eR4et6LR9P19BfFnhGwPfA==
  

Unix:

 "mono encrypt.exe 01/01"
Output:
Pa8pJCYBN7 U R705TFq7Q==
  

Я даже попытался ввести входное значение в скрипт, а затем скомпилировать и запустить его снова, и я получил те же результаты.

Функция decrypt расположена в удаленной веб-службе и использует жестко закодированные значения key и IV (я использую эти значения для шифрования), вывод расшифровки:

 Input (String generated on windows):
eR4et6LR9P19BfFnhGwPfA==
Output:
01/01

Input (String generated on Unix):
Pa8pJCYBN7 U R705TFq7Q==
Output:
????1
  

Это функция шифрования:

 string text = args[0];
byte[] clearData = Encoding.Unicode.GetBytes(text);
PasswordDeriveBytes bytes = new PasswordDeriveBytes(password, new byte[] { 0x19, 0x76, 0x61, 110, 0x20, 0x4d, 0x65, 100, 0x76, 0x65, 100, 0x65, 0xf6 });
string a = Convert.ToBase64String(Encrypt(clearData, bytes.GetBytes(0x20), bytes.GetBytes(0x10)));
Console.Write(a);

public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
{
    MemoryStream stream = new MemoryStream();
    Rijndael rijndael = Rijndael.Create();
    rijndael.Key = Key;
    rijndael.IV = IV;
    CryptoStream stream2 = new CryptoStream(stream, rijndael.CreateEncryptor(), CryptoStreamMode.Write);
    stream2.Write(clearData, 0, clearData.Length);
    stream2.Close();
    return stream.ToArray();
}
  

Это функция дешифрования (я не могу внести в это изменения):

 byte[] cipherData = Convert.FromBase64String(encryptedString);
PasswordDeriveBytes bytes2 = new PasswordDeriveBytes(password, new byte[] { 0x19, 0x76, 0x61, 110, 0x20, 0x4d, 0x65, 100, 0x76, 0x65, 100, 0x65, 0xf6 });
byte[] buffer2 = Decrypt(cipherData, bytes2.GetBytes(0x20), bytes2.GetBytes(0x10));
string output = Encoding.Unicode.GetString(buffer2);
Console.Write(output); 

public static byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV)
{
        MemoryStream stream = new MemoryStream();
        Rijndael rijndael = Rijndael.Create();
        rijndael.Key = Key;
        rijndael.IV = IV;
        CryptoStream stream2 = new CryptoStream(stream, rijndael.CreateDecryptor(), CryptoStreamMode.Write);
        stream2.Write(cipherData, 0, cipherData.Length);
        stream2.Close();
        return stream.ToArray();
}
  

Комментарии:

1. Я не вижу отладочного кода, гарантирующего, что функция шифрования clearData одинакова на обеих платформах. Вы уверены, что это так? Также я надеюсь, что вы не используете константу IV вне ваших примеров…

Ответ №1:

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

http://social.msdn.microsoft.com/forums/en-US/clr/thread/3df8d5aa-ea99-4553-b071-42a2ea406c7f/

Вы сталкиваетесь с этой проблемой, когда КЛЮЧ, IV и ЗАШИФРОВАННЫЕ ДАННЫЕ имеют не все правильные размеры блоков и «схему». Единственный способ избежать этой проблемы — использовать IV и КЛЮЧ, сгенерированный алгоритмом. Вы можете использовать GenerateIV, чтобы получить алгоритм для генерации вам IV. Храните это где-нибудь в безопасном месте, так как вам это понадобится. Затем просто вызовите метод encrypt и передайте данные. Затем алгоритм зашифрует данные и присвоит свойству Key значение вновь сгенерированного ключа. Сохраните это вместе со своими зашифрованными данными. Вот и все, что от нее требуется.

Хотя это устарело, ответ о том, что существуют различные причины различия, но если вы можете расшифровать, то причины различия могут быть действительными, приведен здесь: http://lists.ximian.com/pipermail/mono-list/2006-November/033456.html

Итак, если вы можете зашифровать на одном и расшифровать на другом (вы можете это сделать?), то какая разница, если результаты разные?

Комментарии:

1. Я отправляю зашифрованные данные в веб-службу, которая расшифровывает их и сохраняет в базе данных. Проблема в том, что я не могу изменить функцию decrypt. Ключ и IV жестко закодированы в функции decrypt, поэтому мне нужно использовать указанные ключ и IV при шифровании. Проблема в том, что когда я расшифровываю строку, зашифрованную mono, я получаю???? перед строкой, и это неприемлемо.

2. @user735247 — Возможно ли, что в argv[0] есть некоторый пробел? Возможно, вы захотите использовать String . Trim() для этой строки, чтобы избавиться от любых дополнительных пробелов.

3. Кроме того, при расшифровке используется декодирование base-64 перед расшифровкой?

4. я попытался установить значение внутри кода text =»01/01″ вместо text =argv [0], и у меня все еще та же проблема. Да, я использую Convert.Из Base64String(encryptedString) я добавил функцию дешифрования, используемую веб-службой

Ответ №2:

Возможно, проблема в том, что выходные данные являются unicode, а терминал отображает ascii. Я обычно вижу? вместо неправильно понятых символов Юникода.

Проверьте числовые значения массива байтов и количество.

Ascii вдвое меньше, чем в Unicode, поскольку на каждый символ приходится по два байта.

Комментарии:

1. Декодированная строка в Unix: 98 57 2 57 219 64 199 165 49 0 => ????1 Декодированная строка Windows: 48 0 49 0 47 0 48 0 49 0 => 01/01

Ответ №3:

Вы проверили свою тестовую строку на наличие новых строк? Тестовая строка Windows будет иметь возврат каретки перевод строки, в то время как строка Unix будет иметь только перевод строки.