14.02.2007 17:33:44ошибка 80090020h - NTE_FAIL при вызове CryptEncrypt Ответов: 6
slow
с чем м.б. связана?
RNG установлены аж 3 в т.ч. биологический
КриптоПро 2.0 build 2049

код

function TCrypter.EncryptByPubKey(pbPublicKeyBytes: PByte; cbBytesCount: Cardinal; aiKeyAlg: Cardinal; inp_data: TStream; out_data: TStream; iv: TStream; pubkey: TStream; session: TStream): Boolean;
var
hk: HCRYPTKEY;
pbKeyBlobSimple, pbIV, pbContent: PByte;
dwbloblensimple, dwIV, cbContent: dword;
hAgreeKey, hSessionKey: HCRYPTKEY;
blocklen, cbbl: dword;
r: TReader;
begin
result := false;
//--------------------------------------------------------------------
// Получение дескриптора закрытого ключа отправителя.

if not(CryptGetUserKey(hProv,AT_KEYEXCHANGE,@hk)) then
begin
exit;
end;

//--------------------------------------------------------------------
// Получение ключа согласования импортом открытого ключа получателя
// на закрытом ключе отправителя.


if not(CryptImportKey(
hProv,
pbPublicKeyBytes,
cbBytesCount,
hk,
CRYPT_EXPORTABLE,
@hAgreeKey)) then
begin
raise TCryptException.Create(ceOtherCryptError);
end;

//--------------------------------------------------------------------
// Генерация сессионного ключа.

if not(CryptGenKey(
hprov,
aiKeyAlg,
CRYPT_EXPORTABLE,
@hSessionKey)) then
begin
writeln(getlasterror);
exit;
end;

//--------------------------------------------------------------------
// Зашифрование сессионного ключа.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа сессионного ключа и распределение памяти.
dwbloblensimple := 0;

try
if not(CryptExportKey(
hSessionKey,
hAgreeKey,
SIMPLEBLOB,
0,
nil,
Addr(dwBlobLenSimple))) then
begin
exit;
end;

except
on e: Exception do writeln(e.Message);
end;

getmem(pbKeyBlobSimple, dwBlobLenSimple);

//--------------------------------------------------------------------
// Зашифрование сессионного ключа на ключе Agree.

if not(CryptExportKey(
hSessionKey,
hAgreeKey,
SIMPLEBLOB,
0,
pbKeyBlobSimple,
Addr(dwBlobLenSimple))) then
begin
exit;
end;

//--------------------------------------------------------------------
// Определение размера вектора инициализации сессионного ключа.

if not(CryptGetKeyParam(
hSessionKey,
KP_IV,
nil,
Addr(dwIV),
0)) then
begin
exit;
end;

getmem(pbiv, dwiv);

//--------------------------------------------------------------------
// Определение вектора инициализации сессионного ключа.

if not (CryptGetKeyParam(
hSessionKey,
KP_IV,
pbIV,
addr(dwIV),
0)) then
begin
exit;
end;

//--------------------------------------------------------------------
// Запись вектора инициализации

iv.Write(pbIV, dwIV);

//--------------------------------------------------------------------
// Запись зашифрованного сессионного ключа

session.Write(pbKeyBlobSimple,dwBlobLenSimple);

//--------------------------------------------------------------------
// Чтение данных, которые будут зашифрованы блоками по 4 КБ

CryptGetKeyParam(hSessionKey, KP_BLOCKLEN, Addr(blocklen),addr (cbBl),0);
if cbbl<>0 then;

r := Treader.Create(inp_data,512);
pbContent := AllocMem(512);

repeat
cbContent := inp_data.Read(pbContent^, cbbl * 64);
if cbContent <> 0 then
begin
// Зашифрование прочитанного блока на сессионном ключе.
if not (CryptEncrypt( //--- возвращает false
hSessionKey,
0,
TRUE,
0,
pbContent,
PDWORD(&cbContent),
cbbl * 64)) then
begin
writeln(getlasterror); //--- = NTE_FAIL
exit;
end;
out_data.Write(pbContent,cbContent)
end;
until (inp_data.Position >= inp_data.Size-1) or (cbContent = 0);

result := true;

end;
 
Ответы:
14.02.2007 18:05:47Kirill Sobolev
А hprov откуда берется? ДСЧ непричем здесь.
15.02.2007 9:54:07slow
hProv:


constructor TCrypter.Create(pszContainerName, pszProviderName: PAnsiChar; dwProviderType: Dword);
begin
if not CryptAcquireContext(@hProv, pszContainerName, pszProviderName, dwProviderType, 0) then
raise TCryptException.Create(ceCryptContextNotAcquired);
end;

Вызов делается так
crypter := TCrypter.Create('C15C8B0757C2212A',CP_GR3410_2001_PROV_A,
PROV_GOST_2001_DH);

...

crypter.EncryptByPubKey(cert.PublicKey,CALG_G28147,inp_data,out_data,iv,pubkey,session);

cert.PublicKey это CERT_PUBLIC_KEY_INFO соотв. сертификата (он 100% правильный)
далее экспортируется публичный ключ

function TCrypter.EncryptByPubKey(PubKeyInfo:CERT_PUBLIC_KEY_INFO; aiKeyAlg: DWORD; inp_data: TStream; out_data: TStream; iv: TStream; pubkey, session: TStream): Boolean;
var hPubKey: HCRYPTKEY;
dwDataLen: DWORD;
pbKeyBytes: PByte;
begin
result := false;
if CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,@PubKeyInfo,@hPubKey) then
if CryptExportKey(hpubKey,0,PUBLICKEYBLOB,0,nil,@dwDataLen) then
begin
GetMem(pbKeyBytes, dwDataLen);
if CryptExportKey(hPubKey,0,PUBLICKEYBLOB,0,pbKeyBytes,@dwDataLen) then
result := EncryptByPubKey(pbKeyBytes,dwDataLen,aiKeyAlg,inp_data,out_data,iv,pubkey,session);
end;
end;

15.02.2007 11:01:50Kirill Sobolev
А чему равны cbContent и cbbl до вызова CryptEncrypt?
15.02.2007 11:51:43slow
вместо
cbbl * 64
ставил, например, 4096 - результат аналогичный.

cbbl = 4
cbContent = 256 т.е. 4 * 64
15.02.2007 11:55:17slow
в CryptEncrypt ставил FALSE вместо TRUE. результат аналогичный
15.02.2007 16:42:42slow
PDWORD(&cbContent) заменяем на Addr(cbContent), и все ОК.