28.05.2007 1:46:33CryptImportKey - NTE_BAD_TYPE Ответов: 1
Влад
Здравствуйте. При попытке импорта сеансового ключа получаю ошибку NTE_BAD_TYPE. Ниже привожу код на Delphi как все пытался сделать. Этот код работает с криптопровайдером Microsoft. Подскажите, пожалуйста, где я совершил ошибку.

// * * Генерация
if not CryptAcquireContext(@hProv, cont, 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider', 75, CRYPT_NEWKEYSET) then <Error...>
keyLen := 512;
flag := keyLen shl 16;
if not CryptGenKey(hProv, AT_KEYEXCHANGE, flag, @KeyExchKey) then <Error...>

flag := 4;
if not CryptGetKeyParam(KeyExchKey, KP_KEYLEN, @keyLen, @flag, 0) then <Error...>
{длинна - 512}

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


// * * Экспорт ключа
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);

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

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

AssignFile(f, SaveDialog1.FileName);
rewrite(f, 1);
BlockWrite(f, pbuf^, bufLen);
CloseFile(f);

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




// * * Шифрование
if not CryptAcquireContext(@hProv, cont, 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider', 75, 0) then <Error...>

//читаем файл с открытым ключом обмена ключами получателя
AssignFile(outfile, OpenDlg.FileName);
reset(outfile, 1);
keyLen := FileSize(outfile);
GetMem(tmp, keyLen);
BlockRead(outfile, tmp^, keyLen);
CloseFile(outfile);

// Получение дескриптора закрытого ключа отправителя.
{Не знаю зачем надо, но без нее CryptExportKey выдаст ошибку}
if not CryptGetUserKey(hProv,AT_KEYEXCHANGE,@hk) then <Error...>

// Импорт ключа, опять же надо hk или ставить 0
if not CryptImportKey(hProv, tmp, keyLen, hk, CRYPT_EXPORTABLE, @KeyExchKey) then <Error...>
FreeMem(tmp, keyLen);


rewrite(outfile, 1);
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...>
BlockWrite(outfile, keyLen, 4);
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...>
BlockWrite(outfile, keyLen, 4);
BlockWrite(outfile, buf, keyLen);

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...>

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




// * * Расшифровка
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, @KeyExchKey) then <Error...>

// Чтение зашифрованного файла
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...>
Error -- NTE_BAD_TYPE
 
Ответы:
28.05.2007 11:11:10Василий
Экспорт и импорт сессионного ключа возможен только на ключе парной связи (Диффи-Хеллмана).
Ключ Д-Х получается импортом блоба PUBLICKEYBLOB на ключе AT_KEYEXCHANGE.
При шифровании Вы сделали правильно.

При расшифровании нужно сделать симметрично:
1) создание ключа Д-Х: чтение блоба PUBLICKEYBLOB из файла и импорт его на ключе AT_KEYEXCHANGE
2) чтение блоба сессионного ключа из файла и иморт его на ключе, созданном в предыдущем пункте