ну и сама функция GetHashStream().. больше мне пока добавить нечего...
procedure GetHashStream(Container: WideString; DataStream: TStream; CertStream, KeyStream, HashStream, SignStream: TStream);
var
hProv: HCRYPTPROV;
DataLen: DWORD;
hHash: HCRYPTHASH;
hKey: HCRYPTKEY;
dwKeySpec: DWORD;
InStream, OutStream: TBytesStream;
begin
dwKeySpec:=AT_KEYEXCHANGE; //AT_SIGNATURE
InStream:=TBytesStream.Create;
OutStream:=TBytesStream.Create;
try
CopyStream(DataStream,InStream);
CryptCheck(CryptAcquireContext(@hProv, @Container[1], nil, PROV_GOST_2001_DH, 0), 'CryptAcquireContext');
try
if (CertStream<>nil) or (KeyStream<>nil) then
begin
CryptCheck(CryptGetUserKey(hProv, dwKeySpec, @hKey), 'CryptGetUserKey');
try
//получение сертификата
if CertStream<>nil then
begin
CryptCheck(CryptGetKeyParam(hKey, KP_CERTIFICATE, nil, @DataLen, 0), 'CryptGetKeyParam');
OutStream.Size:=DataLen;
CryptCheck(CryptGetKeyParam(hKey, KP_CERTIFICATE, OutStream.Memory, @DataLen, 0), 'CryptGetKeyParam');
CopyStream(OutStream,CertStream);
end;
//получение открытого ключа
if KeyStream<>nil then
begin
CryptCheck(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, nil, @DataLen), 'CryptExportKey');
OutStream.Size:=DataLen;
CryptCheck(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, OutStream.Memory, @DataLen), 'CryptExportKey');
CopyStream(OutStream,KeyStream);
end;
finally
CryptCheck(CryptDestroyKey(hKey),'CryptDestroyKey');
end;
end;
if (HashStream<>nil) or (SignStream<>nil) then
begin
CryptCheck(CryptCreateHash(hProv, CALG_GR3411, 0, 0, @hHash), 'CryptCreateHash');
try
CryptCheck(CryptHashData(hHash, InStream.Memory, InStream.Size, 0), 'CryptHashData');
//получение хеша
if HashStream<>nil then
begin
CryptCheck(CryptGetHashParam(hHash, HP_HASHVAL, nil, @DataLen, 0), 'CryptGetHashParam');
OutStream.Size:=DataLen;
CryptCheck(CryptGetHashParam(hHash, HP_HASHVAL, OutStream.Memory, @DataLen, 0), 'CryptGetHashParam');
CopyStream(OutStream,HashStream);
end;
//подпись хеша
if SignStream<>nil then
begin
CryptCheck(CryptSignHash(hHash, dwKeySpec, nil, 0, nil, @DataLen), 'CryptSignHash');
OutStream.Size:=DataLen;
CryptCheck(CryptSignHash(hHash, dwKeySpec, nil, 0, OutStream.Memory, @DataLen), 'CryptSignHash');
CopyStream(OutStream,SignStream,True); //с обязательным переворачиванием
end;
finally
CryptCheck(CryptDestroyHash(hHash), 'CryptDestroyHash');
end;
end;
finally
CryptCheck(CryptReleaseContext(hProv, 0), 'CryptReleaseContext');
end;
finally
InStream.Free;
OutStream.Free;
end;
end;