Функция CryptDeriveKey, согласно мсдн, генерит "хороший" в статистическом смысле сеансовый ключ, однозначно определяемый хешем. Но это не значит, что этот сеансовый ключ равен этому хешу! И алгоритм, которым пользуется MS для генерации ключа на основании хеша не специфицирован. То есть если ты суешь в не-MS библиотеку хеш, полученный MD5, в качестве сесансового ключа, результат в принципе на может совпасть с CryptoAPI.
Если хочешь поставить чистый эксперимент, надо импортировать в ключевой объект микросовта "сырой" сеансовый ключ. Сделать это можно с помощью вырожденного ключа RSA, который обычно используется для экспорта/импорта сеансового ключа в функцию. У MS есть пример, как это сделать. Поищи в мсдн по ключевым словам exponent one.
Итак. Использовав MicroSoft CryptoAPI создал RC4 модуль. Криптует, декрептует - все ОК.
Скачал из инета исходники RC4, откомпилил, собрал модуль - криптует, декрептует, зашибись, все ОК.
А теперь одну и туже последовательность даных (key, data) скармливаю MS и Inet модулям. Опс ! А выходная последовательность - разная !
Хорошо, думаю, в MS ключ генерится из hash зделаным MD5. Беру модуль (опять же с инета) MD5, прогоняю через него ключ, получаю хеш, скармлеваю этот хеш и даные Inet модулю RC4... неа, опять не та последовательность, что MS RC4 выдает.
Даже и не знаю в чем дело...
Вот как я генерю ключ в MS, может тут ошибка ?
unsigned long NASCryptoProvider::GenDelivK( CHAR* szPassword, DWORD dwLength)
{
//--------------------------------------------------------------------
// Declare and initialize variables.
HCRYPTKEY hKey;
HCRYPTHASH hHash;
//--------------------------------------------------------------------
// Acquire a CSP.
//--------------------------------------------------------------------
// Create an empty hash object.
if(CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash))
{
// printf("An empty hash object has been created. \n");
}
else
{
HandleError("Error during CryptCreateHash!");
}
//--------------------------------------------------------------------
// Hash the password string.
if(CryptHashData(
hHash,
(BYTE *)szPassword,
dwLength,
0))
{
// printf("The password has been hashed. \n");
}
else
{
HandleError("Error during CryptHashData!");
}
//--------------------------------------------------------------------
// Create a session key based on the hash of the password.
if(CryptDeriveKey(
hCryptProv,
CALG_RC4,
hHash,
CRYPT_EXPORTABLE,
&hKey))
{
// printf("The key has been derived. \n");
}
else
{
HandleError("Error during CryptDeriveKey!");
}
//--------------------------------------------------------------------
// Use hKey as appropriate to encrypt or decrypt a message.
Возникает непреодолимое желание решить, что реализация взятая из inet просто не корректна.
Я скачал OpenSSL библиотеку с ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/ Откомпилил модуль RC4. Результаты совпали с модулем взятым перед этим из inet. Естественно не совпали с результатом работы MS CryptoAPI.
Очнь буду рад, если кто нибудь объяснит эту мистику.
Если еще не решил проблему, то есть одня мысль...24.09.01 16:23 Автор: prop Статус: Незарегистрированный пользователь
Функция CryptDeriveKey, согласно мсдн, генерит "хороший" в статистическом смысле сеансовый ключ, однозначно определяемый хешем. Но это не значит, что этот сеансовый ключ равен этому хешу! И алгоритм, которым пользуется MS для генерации ключа на основании хеша не специфицирован. То есть если ты суешь в не-MS библиотеку хеш, полученный MD5, в качестве сесансового ключа, результат в принципе на может совпасть с CryptoAPI.
Если хочешь поставить чистый эксперимент, надо импортировать в ключевой объект микросовта "сырой" сеансовый ключ. Сделать это можно с помощью вырожденного ключа RSA, который обычно используется для экспорта/импорта сеансового ключа в функцию. У MS есть пример, как это сделать. Поищи в мсдн по ключевым словам exponent one.
Но что тогда получается !24.09.01 18:28 Автор: PS <PS> Статус: Elderman
Пусть я на одном и том же хеше строю ключ, и он в MS и не в MS различный, то:
Нет возможности написать прогу Win - Unix, где на Win строне пользуюсь MS CryptoAPI, а на Unix другой реализацией ТОГО-ЖЕ алгоритма.
Если это так, то MS, извиняюсь, писает против ветра.
Обязательно еще поэксперементирую как только руки дойдут.
Спасибо.
P.S. А вообще RC4 лучше не пользовать - лицензию с него еще никто не убирал. :(
Тогда все OK25.09.01 11:37 Автор: prop Статус: Незарегистрированный пользователь
> Пусть я на одном и том же хеше строю ключ, и он в MS и не в > MS различный, то: Надо строить ключ самому, без MS.
> Нет возможности написать прогу Win - Unix, где на Win > строне пользуюсь MS CryptoAPI, а на Unix другой реализацией > ТОГО-ЖЕ алгоритма. Можно, если на обеих платформах использовать импорт сырого сеансового ключа - в MS - через %опу (exponent one), а в унихе не знаю через что
> Если это так, то MS, извиняюсь, писает против ветра. Ну это билл давно делает и пока обтекает
> > Обязательно еще поэксперементирую как только руки дойдут. > Спасибо. :-)))
> > P.S. А вообще RC4 лучше не пользовать - лицензию с него еще > никто не убирал. :(
Вот результаты моих тестов(вдруг кому интересно)13.09.01 19:31 Автор: PS <PS> Статус: Elderman
MicroSoft (MS) RC4:
User Key set: 0x1 0x23 0x45 0x67 0x89 0xab 0xcd 0xef
In data set: 0x1 0x23 0x45 0x67 0x89 0xab 0xcd 0xef
Out data set: 0x99 0x79 0x1f 0x56 0xca 0x36 0x67 0xe9
Inet RC4:
User Key set: 0x1 0x23 0x45 0x67 0x89 0xab 0xcd 0xef
In data set: 0x1 0x23 0x45 0x67 0x89 0xab 0xcd 0xef
Out data set: 0x75 0xb7 0x87 0x80 0x99 0xe0 0xc5 0x96
Выход совпадает с приведеным тестом в readme, прилогаемом к исходникам. Но не совпадает с MS.
Теперь перед генерацией ключа, я пропустил User Key через MD5:
Inet RC4 with MD5 hash:
User Key set: 0x1 0x23 0x45 0x67 0x89 0xab 0xcd 0xef
In data set: 0x1 0x23 0x45 0x67 0x89 0xab 0xcd 0xef
Out data set: 0xfb 0x9f 0xca 0xa9 0x17 0x70 0x37 0x7f
Все равно не совпало с MS !
Усомнившись в адекватности генерации хеша либо в MS, либо у меня, проверил MD5:
HASH MS MD5:
PASSW: 01 23 45 67 89 AB CD EF
HASH : A1 CD 1D 1F C6 49 10 68 D9 10 07 28 3E D8 44 89
HASH MY MD5:
PASSW: 01 23 45 67 89 AB CD EF
HASH : A1 CD 1D 1F C6 49 10 68 D9 10 07 28 3E D8 44 89
Хеши совпали !
Итак возможно есть разница в генерации ключей. К сожалению в MS не смог добраться к внутренему представлению RC4 ключа :(
Решил сделать хеш с ключа в MS, а так же сериализовать структуру rc4_key у себя, сделать хеш и сравнить их. Вот что получилось:
HASH OF KEY RC4 BY MD5 IN MS:
HASH: DF 84 0B A7 85 DB 99 23 CB DF 47 E5 2C DB 2F 4B
X = Y = 0 : NOT ALL COMBINATION TESTED !
HASH OF KEY RC4 BY MD5 IN INET(SERIALIZED 1 COMBINATION: state,x,y):
HASH: 18 0B 0E 69 48 0E 93 1E 63 B0 84 12 36 92 38 D1
HASH OF KEY RC4 BY MD5 IN INET(SERIALIZED 2 COMBINATION: x,y,state):
HASH: A9 1C 20 A4 3D EB 57 C0 5B 3A 11 9D 25 0A 4C 1A
HASH OF KEY RC4 BY MD5 IN INET(SERIALIZED 3 COMBINATION: x,state,y):
HASH: 05 81 10 00 16 D7 41 E5 81 31 59 3E F1 6A E1 AF
Как видно не одна комбинация сериализации не дала той же хешевой последовательности, что и MS !
Либо ключ генеренный MS и модулем из Inet различны, либо MS хитро сериализует ключ, прежде чем его хешировать.
Так у меня и не получилось разобраться из-за чего возникает разница на выходе в этих двух реализациях алгоритма. :((((
Вот результаты моих тестов(вдруг кому интересно)14.09.01 23:44 Автор: leo <Леонид Юрьев> Статус: Elderman
По сути дела могу посоветовать следующий список "граблей":
- дополнение ключа нулями до необходимой длины;
- длина ключа как часть ключа;
- порядок байтов;