Автор: maxdm Можно кусочек кода?
// Код на Delphi, но архитуктура, я думаю, ясно.
var
hStore: HCERTSTORE;
pCert: PCCERT_CONTEXT;
RefCert: CERT_INFO;
pProvKey: PCRYPT_KEY_PROV_INFO;
dwProvKeyInfoSize: DWORD;
hProvider: HCRYPTPROV;
CadesSignPara: CADES_SIGN_PARA;
CryptSignMessagePara: CRYPT_SIGN_MESSAGE_PARA;
CadesSignMessagePara: CADES_SIGN_MESSAGE_PARA;
rgpbToBeSigned: PBYTE;
rgcbToBeSigned: DWORD;
pSignedMessage: PCRYPT_DATA_BLOB;
Pin: PAnsiChar;
const
SN: array [0..9] of byte = ($15, $b8, $fb, $e9, $00, $02, $00, $03, $15, $b1);
Issuer: PAnsiChar = 'CN = Test Center CRYPTO-PRO O = CRYPTO-PRO C = RU E =
info@cryptopro.ru';
begin
// Ищем определённый сертификат в хранилище
hStore := CertOpenSystemStore(0, 'MY');
if hStore = nil then Exit;
FillMemory(@RefCert, SizeOf(RefCert), 0);
RefCert.Issuer.cbData := Length(Issuer);
RefCert.Issuer.pbData := Pointer(Issuer);
RefCert.SerialNumber.cbData := 9;
RefCert.SerialNumber.pbData := @SN;
pCert := CertGetSubjectCertificateFromStore(hStore, X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, ACert.FCertContext^.pCertInfo);
if pCert = nil then Exit;
// Залезаем в контейнер
pProvKey := nil;
dwProvKeyInfoSize := 0;
CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, pProvKey, @dwProvKeyInfoSize);
GetMem(pProvKey, dwProvKeyInfoSize);
if not CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, pProvKey, @dwProvKeyInfoSize) then Exit;
if not CryptAcquireContextW(@hProvider, pProvKey^.pwszContainerName, pProvKey^.pwszProvName, pProvKey^.dwProvType, CRYPT_MACHINE_KEYSET) then Exit;
// Передаём пароль провайдеру
Pin := 'eToken1*';
if not CryptSetProvParam(hProvider, PP_SIGNATURE_PIN, PBYTE(Pin), 0) then Exit;
// Создаём подпись.
// Среди параметров CadesSignMessage нет hProvider. Но другие криптопровайдеры, очевидно, при вызове CryptSetProvParam
// взводят свои внутренние глобальные переменные и запоминают пароль к контейнеру.
FillMemory(@CadesSignPara, SizeOf(CadesSignPara), 0);
CadesSignPara.dwSize := SizeOf(CadesSignPara);
CadesSignPara.dwCadesType := CADES_BES;
FillMemory(@CryptSignMessagePara, SizeOf(CryptSignMessagePara), 0);
CryptSignMessagePara.cbSize := SizeOf(CryptSignMessagePara);
CryptSignMessagePara.dwMsgEncodingType := X509_ASN_ENCODING or PKCS_7_ASN_ENCODING;
CryptSignMessagePara.pSigningCert := pCert;
CryptSignMessagePara.HashAlgorithm.pszObjId := '1.2.643.2.2.9';
FillMemory(@CadesSignMessagePara, SizeOf(CadesSignMessagePara), 0);
CadesSignMessagePara.dwSize := SizeOf(CryptSignMessagePara);
CadesSignMessagePara.pSignMessagePara := @CryptSignMessagePara;
CadesSignMessagePara.pCadesSignPara := @CadesSignPara;
pSignedMessage := nil;
rgpbToBeSigned := @SN;
rgcbToBeSigned := 5;
if not CadesSignMessage(@CadesSignMessagePara, True, 1, @rgpbToBeSigned, @rgcbToBeSigned, pSignedMessage) then Exit;
ShowMessage('OK');