28.04.2007 16:41:43Ошибка импорта Ответов: 13
Антон Макаров
Не получается сделать импорт блоба открытого ключа получателя на своей ключевой паре. Делаю так:

hFile1 = ::CreateFile ("c:\\BLOB.key", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hFile1) { Form1->Memo1->Lines->Add("Pub key file IO error"); return false; }
DWORD dwSize = ::GetFileSize (hFile1, NULL);
::ReadFile (hFile1, szPubKey, dwSize, &dwPubKeySize, NULL);
::CloseHandle (hFile1);
if (dwSize != dwPubKeySize) { Form1->Memo1->Lines->Add("Pub key file read error"); return false; }

// 1) Initialize CryptoAPI
bRes = CryptAcquireContext (&hCryptProv, NULL, NULL, DEF_PROV, 0);
if (bRes) Form1->Memo1->Lines->Add("CryptAcquireContext () ... OK");
else Form1->Memo1->Lines->Add("Can't initialize CryptoAPI");

// Get User key
if (!CryptGetUserKey(hCryptProv, AT_KEYEXCHANGE, &hUserKey))
Form1->Memo1->Lines->Add("Can't get user key");
else Form1->Memo1->Lines->Add("CryptGetUserKey success");

// 2) Create session key
//CryptGenKey (ïðîâàéäåð, àëãîðèòì, ôëàãè, êëþ÷)
bRes = CryptGenKey(hCryptProv, CALG_G28147, CRYPT_EXPORTABLE, &hSesKey);
if (bRes) Form1->Memo1->Lines->Add("CryptGenKey (session) ... OK");
else Form1->Memo1->Lines->Add("CryptGenKey (session) error");

// 3) Import public key
bRes = CryptImportKey (hCryptProv, (BYTE *)&szPubKey[0], dwPubKeySize, hUserKey, 0, &hPPKey);
if (bRes) Form1->Memo1->Lines->Add("CryptImportKey (public) ... OK");
else {Form1->Memo1->Lines->Add("CryptImportKey (public) error"); GetLastError(); return false;}

На импорте выходит ошибка. В чем может быть проблема? Делаю все по примерам на этом форуме...
 
Ответы:
28.04.2007 17:03:04Kirill Sobolev
Какая ошибка?
28.04.2007 17:35:09Макаров Антон
GetLastError() возвращает 5 (не знаю к сожалению как посмотреть по предопределенным значениям).
29.04.2007 0:16:09maxdm
хм. странная последовательность вызовов - что сделать то пытаетесь?
29.04.2007 21:12:23Макаров Антон
Я пытаюсь зашифровать данные. Сначала создаю сессионный ключ и затем импортирую открытый ключ получателся на своей ключевой паре для получения ключа парной связи. Если что-то делаю не так - поправьте пожалуйста.
02.05.2007 11:35:23Василий
Можно уточнить значения:
1) DEF_PROV
2) dwPubKeySize (после чтения файла)
3) алгоритмы ключей AT_KEYEXCHANGE - отправителя и получателя
02.05.2007 12:26:28Макаров Антон
1) #define DEF_PROV 75
2) dwPubKeySize = 164 байта
3) это задается в сертификате открытого ключа? если да, то алгоритмы ГОСТ Р 34.10-94
02.05.2007 14:27:39Василий
В сертификате - про открытый ключ.
А в Вашем контейнере, судя по всему, алгоритм ключа (AT_KEYEXCHANGE) ГОСТ... 2001.
Если Вы создавали контейнер на CSP 75-го типа и не указали конкретный алгоритм при создании ключа AT_KEYEXCHANGE - то он будет 2001-го ГОСТа.
Импорт открытого ключа для создания ключа Диффи-Хеллмана возможен только при совпадении алгоритмов (открытого ключа и своего ключа AT_KEYEXCHANGE) - либо оба ГОСТ 94, либо оба 2001.
02.05.2007 15:03:39Макаров Антон
Спасибо за разъяснение!
Я в этом форуме в одной из веток читал, что если БЛОБ 164 байта, то это 94 год, а если 100 байт - 01 год. Открытый ключ таким образом у меня 94 года, а как мне указать AT_KEYEXCHANGE 94 года? через установку параметров ключа?
02.05.2007 15:31:24Василий
Лучше сделайте новый ключевой контейнер на CSP не 75-го, а 71-го типа. И в нём ключ AT_KEYEXCHANGE.

Кстати, по информации из ЦБС ФСБ: ГОСТ Р 34.10-94 разрешается использовать для подписи только до 31 декабря 2007 года. Далее только для проверки подписи. Есть мнение, что и для согласования ключей ГОСТ 94-го года скоро будет запрещён (точная дата пока не определена) или, во всяком случае, будет ограничен гарантированыый срок сохранения в тайне информации при применении для согласования ключей ГОСТа 94-го года.
02.05.2007 16:38:51Макаров Антон
Как можно указать тип CSP для ключевого контейнера? Когда я делаю "Установить личный сертификат" там явно не выбирается CSP. Или это не интерактивно, а программно устанавливается?
02.05.2007 19:11:28Василий
В Вашем сообщении от 28.04.2007 16:41:43
есть вызов
CryptAcquireContext (&hCryptProv, NULL, NULL, DEF_PROV, 0);
т.е. открыть существующий контейнер с именем по умолчанию на криптопровайдере (CSP) 75-го типа.
Раз контейнер существующий, значит, кто-то его создал. Это можно было сделать программно (CryptAcquireContext с флажком CRYPT_NEWKEYSET) или при создании запроса на сертификат. Во время создания и выбирался алгоритм ключа AT_KEYEXCHANGE (ГОСТ 94 или 2001). Изменить алгоритм ключа после создания нельзя. Можно только сделать новый ключ.
02.05.2007 21:47:54Макаров Антон
Прошу прощение за возможное дилетанство, но я создал контейнер не программно и не через запрос на сертификат. У меня была дискета с закрытым ключом и файл *.cer с сертификатом открытого ключа. Я зашел в настройки криптопровайдера, сделал "установить личный сертификат" и у меня появился контейнер. Получается, по умолчанию у меня AT_KEYEXCHANGE получился 2001 года. При таком способе установки можно что-то исправить. Может алгоритм AT_KEYEXCHANGE задается в сертификате открытого ключа?
03.05.2007 9:54:11Василий
Ещё раз повторю - алгоритм ключа задаётся при создании ключевого контейнера, поменять его нельзя.
Если в Вашем контейнере ключ ГОСТ 2001, а в чужом блобе открытого ключа - 94, то создать ключ парной связи (Диффи-Хеллмана) невозможно.
Однако, если бы у Вас был сертификат получателя (а не блоб открытого ключа), то можно организовать процедуру шифрования при использовании более высокоуровневых функций CryptoAPI, например, CryptEncryptMessage