Решал похожую задачу используя CryptoCSP от компании CryptoPro (
документация по теме). Это обертка на работу с сертификатами, можно попробовать поработать через CryptoAPI от Майкрософта, если разберетесь.
Даю пару примеров, чтобы Вы поняли, в каком направлении двигаться:
Пример 1.
// Пример работы с сертификатами. Поиск по номеру сертификата.
// В дельфи номер пишется в обратном порядке!
class function TDigitalSigner.GetCertificateBySerialNumber(const aSerialNumber: string): PCCERT_CONTEXT;
var
hStore: hcertstore;
begin
hStore := CertOpenSystemStore(0, 'MY');
Result := CertFindCertificateInStore(hStore, X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, PChar(aSerialNumber), nil);
end;
Пример 2.
function EncryptAndSign(ASignCertContent: string; AEncCerts: TStringList; FileName, OutFileName: string; out ErrText: string): Boolean;
var
hProv : HCRYPTPROV;
hStoreHandle: hcertstore;
pSignerCert : jwawincrypt.PCCERT_CONTEXT;
encCert : jwawincrypt.CRYPT_DATA_BLOB;
SigParams : jwawincrypt.CRYPT_SIGN_MESSAGE_PARA;
pCertContext: PCCERT_CONTEXT;
Stream : TMemoryStream;
Certificates: array [0 .. 100] of PCCERT_CONTEXT;
EncParams : CRYPT_ENCRYPT_MESSAGE_PARA;
cbEncrypted : DWORD;
i : integer;
pszObjId : LPSTR;
const
PROV_GOST_2001_DH = 75;
begin
Result := false;
for i := 0 to 100 do
Certificates[i] := nil;
if not jwawincrypt.CryptAcquireContext(hProv, nil, nil, PROV_GOST_2001_DH, CRYPT_VERIFYCONTEXT) then
exit;
hStoreHandle := CertOpenSystemStore(hProv, 'MY');
if (hStoreHandle = nil) then
begin
ErrText := 'ErrorOpenStore';
exit;
end;
for i := 0 to AEncCerts.Count - 1 do
begin
try
encCert := GetCertContent(FileToStr(AEncCerts.Strings[i]));
except
ErrText := 'ErrorCertLoad';
Continue;
end;
pCertContext := jwawincrypt.CertCreateCertificateContext(MYTYPE, encCert.pbData, encCert.cbData);
pCertContext := jwawincrypt.CertFindCertificateInStore(hStoreHandle, MYTYPE, 0, CERT_FIND_EXISTING, pCertContext, nil);
if (pCertContext = nil) then
begin
ErrText := 'ErrorCertInStoreNotFound';
Continue;
end;
Certificates[i] := pCertContext;
end;
encCert := GetCertContent(FileToStr(ASignCertContent));
// Открываем хранилище сертификатов
pSignerCert := nil;
pSignerCert := jwawincrypt.CertCreateCertificateContext(MYTYPE, encCert.pbData, encCert.cbData);
pSignerCert := jwawincrypt.CertFindCertificateInStore(hStoreHandle, MYTYPE, 0, CERT_FIND_EXISTING, pSignerCert, nil);
if (pSignerCert = nil) then
begin
exit;
end;
with TMemoryStream.Create do
try
LoadFromFile(FileName);
try
try
// Инициализация структуры, необходимой для цифровой подписи
pszObjId := szOID_RSA_MD5; // получение алгоритма сертификата
FillChar(SigParams, Sizeof(CRYPT_SIGN_MESSAGE_PARA), #0);
SigParams.cbSize := Sizeof(CRYPT_SIGN_MESSAGE_PARA);
SigParams.dwMsgEncodingType := MYTYPE;
SigParams.pSigningCert := pSignerCert;
SigParams.HashAlgorithm.pszObjId := pszObjId;
// для Сигнал - Com szOID_RSA_MD5;// 1.2.643.2.2.21
SigParams.HashAlgorithm.Parameters.cbData := 0;
SigParams.cMsgCert := 1;
SigParams.rgpMsgCert := @pSignerCert;
SigParams.cAuthAttr := 0;
SigParams.dwInnerContentType := 0;
SigParams.cMsgCrl := 0;
SigParams.cUnauthAttr := 0;
SigParams.dwFlags := 0;
SigParams.pvHashAuxInfo := nil;
SigParams.rgAuthAttr := nil;
ZeroMemory(@EncParams, Sizeof(CRYPT_ENCRYPT_MESSAGE_PARA));
EncParams.cbSize := Sizeof(CRYPT_ENCRYPT_MESSAGE_PARA);
EncParams.dwMsgEncodingType := MYTYPE;
EncParams.HCRYPTPROV := hProv;
EncParams.ContentEncryptionAlgorithm.pszObjId := szOID_CP_GOST_28147;
// Алгоритм шифрования ГОСТ 28147-89 1.2.643.2.2.21
if CryptSignAndEncryptMessage(@SigParams, @EncParams, AEncCerts.Count, @Certificates, Memory, Size, nil, cbEncrypted) then
begin
Stream := TMemoryStream.Create;
try
Stream.SetSize(cbEncrypted);
if CryptSignAndEncryptMessage(@SigParams, @EncParams, AEncCerts.Count, @Certificates, Memory, Size, Stream.Memory, cbEncrypted) then
begin
Stream.SetSize(cbEncrypted);
Stream.SaveToFile(OutFileName);
Result := True;
end
else
ErrText := SysErrorMessage(GetLastError);
finally
FreeAndNil(Stream);
end;
end
else
ErrText := SysErrorMessage(GetLastError);
except
ErrText := SysErrorMessage(GetLastError);
end;
finally
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
end;
finally
Free;
end;
end;