D
D
Dmitry Filyushin2016-02-15 07:01:30
Delphi
Dmitry Filyushin, 2016-02-15 07:01:30

How to use digital signature in .p12 file in Delphi?

There is an EDS in PKCS12 format. It is necessary to read the certificate, determine the owner, the relevance of the certificate (date of issue, date of expiration). It is solved, I think that through OpenSSL. Have you seen wrappers for functions, optimized headers for Delphey, ready-made working code for examples?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Maxim Tikhonov, 2016-02-26
@mylp

Solved a similar problem using CryptoCSP from CryptoPro ( documentation on the topic ). This is a wrapper for working with certificates, you can try to work through Microsoft's CryptoAPI if you figure it out.
I give a couple of examples so that you understand in which direction to move:
Example 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;

Example 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;

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question