Функция шифрования дает разные результаты в Windows и Unix.

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

Вот пример:

Окна:

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

Юникс:

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

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

Функция расшифровки находится в удаленной веб-службе и использует жестко закодированный ключ и значения 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();
}

person user735247    schedule 02.05.2011    source источник
comment
Я не вижу кода отладки, гарантирующего, что функция шифрования clearData одинакова на обеих платформах. Вы уверены, что это так? Также я надеюсь, что вы не используете постоянный IV за пределами своих примеров...   -  person Bruno Rohée    schedule 12.05.2011


Ответы (3)


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

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

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

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

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

person James Black    schedule 02.05.2011
comment
Я отправляю зашифрованные данные в веб-службу, которая их расшифровывает и сохраняет в базе данных. Проблема в том, что я не могу изменить функцию расшифровки. Ключ и IV жестко закодированы в функции расшифровки, поэтому мне нужно использовать указанный ключ и IV при шифровании. Проблема в том, что когда я расшифровываю моно зашифрованную строку, я получаю ???? перед строкой, и это неприемлемо. - person user735247; 03.05.2011
comment
@user735247 user735247 - Возможно ли, что в argv[0] есть пробел? Вы можете использовать String.Trim() для этой строки, чтобы избавиться от лишних пробелов. - person James Black; 03.05.2011
comment
Кроме того, когда вы расшифровываете, используете ли декодирование base-64 перед расшифровкой? - person James Black; 03.05.2011
comment
я попытался установить значение внутри кода text=01/01 вместо text=argv[0], и у меня все еще та же проблема. Да, я использую Convert.FromBase64String(encryptedString), я добавил функцию расшифровки, которую использует веб-служба. - person user735247; 03.05.2011

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

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

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

person The Lazy Coder    schedule 03.05.2011
comment
Декодированная строка 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 - person user735247; 03.05.2011

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

person Foozinator    schedule 03.03.2013