29.06.2007 12:46:29CryptImportKey - NTE_BAD_DATA Ответов: 5
Влад
// * * Расшифровка
if not CryptAcquireContext(@hProv, cont, 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider', 75, 0) then <Error...>

if not CryptGetUserKey(hProv, AT_KEYEXCHANGE, @hk) then <Error...>

//Читаю открытый ключ
AssignFile(outfile, OpenDlg.FileName);
reset(outfile, 1);
keyLen := FileSize(outfile);
GetMem(tmp, keyLen);
BlockRead(outfile, tmp^, keyLen);
CloseFile(outfile);

//Импортирую его
if not CryptImportKey(hProv, tmp, keyLen, hk, 0, @KeyExchKey) then <Error...>
FreeMem(tmp, keyLen);

//Читаю сеансовый ключ
reset(infile, 1);
BlockRead(infile, keyLen, 4);
GetMem(tmp, keyLen);
BlockRead(infile, tmp^, keyLen);

//Импортирую его
if not CryptImportKey(hProv, tmp, keyLen, KeyExchKey, 0, @SessionKey) then <Error...>
Получаю ошибку - NTE_BAD_DATA.
Подскажите в чем проблема. Буду признателен за пример кода.
 
Ответы:
29.06.2007 12:56:16Василий
Так не скажешь...
Нужны подробности

Одинаковые ли алгоритмы ключей AT_KEYEXCHANGE отправителя и получателя?
Т.е. в Вашем случае должен быть ГОСТ 2001-го года. Или хотя бы сообщите размеры блобов открытого ключа и сеансового ключа.

Если да - приведите код экспорта ключей (открытого, сеансового), а также - одинаковые ли CSP при экспорте ключей и импорте их?
29.06.2007 14:30:26Влад
Я новичок, поэтому мог что-то напутать.
Уже долго мучаюсь, помогите справиться с проблемой.

Последовательность действий:
Делаю так: Создаю последовательно два тестовых сертификата (http://www.cryptopro.ru/certsrv/) и помещаю их на две дискеты (дискету "а" и дискету "b").
Помещаю дискету "а" и экспортирую ключ обмена ключами в файл "pubkey_a".
Помещаю дискету "b" и с использование "pubkey_a" шифрую файл. Зашифрованный файл - "test_enc.txt".
Помещаю дискету "а" и пытаюсь расшифровать "test_enc.txt".
Получаю ошибку NTE_BAD_DATA.


Код и размеры блоков (Delphi):
I) Экспорт ключа обмена ключами (дискета "а")
if not CryptAcquireContext(@hProv, nil, 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider', 75, 0) then <Error...>

if not CryptGetUserKey(hProv, AT_KEYEXCHANGE, @key) then <Error...>

if not CryptExportKey(key, 0, PUBLICKEYBLOB, 0, nil, @bufLen)) then <Error...>
GetMem(pbuf, bufLen); <<-- bufLen == 100

if not CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pbuf, @bufLen)) then <Error...>

if not CryptDestroyKey(key) then <Error...>

rewrite(f, 1);
BlockWrite(f, pbuf^, bufLen);
CloseFile(f);

if not CryptReleaseContext(hProv, 0) then then <Error...>

Создался файл "pubkey_a". Размер 100 Б




II) Шифрование файла (дискета "b")
if not CryptAcquireContext(@hProv, cont, 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider', 75, 0) <Error...>

//Читаю файл "pubkey_a"
reset(outfile, 1);
keyLen := FileSize(outfile); <<-- keyLen == 100
GetMem(tmp, keyLen);
BlockRead(outfile, tmp^, keyLen);
CloseFile(outfile);

if not CryptGetUserKey(hProv,AT_KEYEXCHANGE,@hk) then <Error...>

if not CryptImportKey(hProv, tmp, keyLen, hk, CRYPT_EXPORTABLE, @KeyExchKey) then <Error...>
FreeMem(tmp, keyLen);

//Генерируем ключ
if not CryptGenKey(hProv, CALG_G28147, CRYPT_EXPORTABLE, @SessionKey) then <Error...>
keyLen := 512;
GetMem(tmp, keyLen);

//Экспортируем
if not CryptExportKey(SessionKey, KeyExchKey, SIMPLEBLOB, 0, tmp, @keyLen) then <Error...>
//Записываем в файл (1)
BlockWrite(outfile, keyLen, 4); <<-- keyLen == 71
BlockWrite(outfile, tmp^, keyLen);

if not CryptDestroyKey(KeyExchKey) then <Error...>

//создание IV
keyLen := 512;
if not CryptGetKeyParam(SessionKey, KP_IV, @buf, @keyLen, 0) then <Error...>
if not CryptGenRandom(hProv, keyLen, @buf) then <Error...>
if not CryptSetKeyParam(SessionKey, KP_IV, @buf, 0) then <Error...>

//Записываем в файл (2)
BlockWrite(outfile, keyLen, 4); <<-- keyLen == 8
BlockWrite(outfile, buf, keyLen);

//Записываем в файл (3)
reset(infile, 1);
while not eof(infile) do
begin
BlockRead(infile, buf, 496, keyLen);
if not CryptEncrypt(SessionKey, 0, eof(infile), 0, @buf, @keyLen, 512) then <Error...>
BlockWrite(outfile, buf, keyLen);
end;
CloseFile(infile);
CloseFile(outfile);

if not CryptDestroyKey(SessionKey) then <Error...>

Создался файл "test_enc.txt".




III) Расшифровка файла (дискета "a")

//Читаю файл "pubkey_a"
reset(outfile, 1);
keyLen := FileSize(outfile);
GetMem(tmp, keyLen); <<-- keyLen == 100
BlockRead(outfile, tmp^, keyLen);
CloseFile(outfile);

if not CryptGetUserKey(hProv,AT_KEYEXCHANGE,@hk) then <Error...>

if not CryptImportKey(hProv, tmp, keyLen, hk, CRYPT_EXPORTABLE, @KeyExchKey) then <Error...>
FreeMem(tmp, keyLen);

//Читаю "test_enc.txt" (1 - сеансовый ключ)
reset(infile, 1);
BlockRead(infile, keyLen, 4); <<-- keyLen == 71
GetMem(tmp, keyLen);
BlockRead(infile, tmp^, keyLen);

if not CryptImportKey(hProv, tmp, keyLen, KeyExchKey, 0, @SessionKey) then <Error...>

Получаю ошибку - NTE_BAD_DATA.
29.06.2007 15:12:37Василий
Почти всё правильно.
Только не хватает:
на этапе II - экспорта в PUBLICKEYBLOB ключа hk из контейнера дискеты б (в файл pubkey_b)

на этапе III - вместо чтения из pubkey_a следует читать из pubkey_b
29.06.2007 16:01:21Влад
Не идет, снова ошибка. Блок (II). Сразу после строки
if not CryptGetUserKey(hProv,AT_KEYEXCHANGE,@hk) then <Error...>
пишу:

if not CryptExportKey(hk, 0, PUBLICKEYBLOB, 0, nil, @bufLen) then <Error...>

GetMem(pbuf, bufLen); <<-- bufLen == 100

if CryptExportKey(hk, 0, PUBLICKEYBLOB, 0, pbuf, @bufLen) then <Error...>
Ошибка!
29.06.2007 17:12:22Влад
Последний вопрос снимается. Сам ошибся.