| ||||
| ||||
с чем м.б. связана? 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; | ||||
Ответы: | ||||
| ||||
А hprov откуда берется? ДСЧ непричем здесь. | ||||
| ||||
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; | ||||
| ||||
А чему равны cbContent и cbbl до вызова CryptEncrypt? | ||||
| ||||
вместо cbbl * 64 ставил, например, 4096 - результат аналогичный. cbbl = 4 cbContent = 256 т.е. 4 * 64 | ||||
| ||||
в CryptEncrypt ставил FALSE вместо TRUE. результат аналогичный | ||||
| ||||
PDWORD(&cbContent) заменяем на Addr(cbContent), и все ОК. | ||||