Как я могу получить доступ к сертификатам корневых центров сертификации Windows с помощью Delphi? - PullRequest
5 голосов
/ 17 ноября 2011

Вопрос, связанный с Лазарем или Дельфи.Есть ли способ программного доступа к доверенным сертификатам корневых центров сертификации в Windows.Я знаю, что в Windows есть инструмент с графическим интерфейсом, называемый mmc.exe, но мне нужен доступ к файлам сертификатов (например, .crt или .cer или .pem и т. Д.) С использованием синтаксиса Object Pascal.Кто-нибудь может мне помочь с этим?

Ответы [ 3 ]

6 голосов
/ 17 ноября 2011

В качестве альтернативы есть CAPICOM , который вы можете просто импортировать как библиотеку типов ActiveX, но есть также простой старый Windows Cryptography API .

В качестве примера, вот мой очень старый мой тестовый проект (я недавно не пробовал). Вам понадобится модуль WinCrypt или JwaWinCrypt с соответствующими переводами API, которые должны быть доступны на JEDI :

program lstore;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  WinCrypt;

var
  StoreName: array[0..255] of Char;
  hStore: HCERTSTORE;
  CertContext: PCertContext;
  CertPropId: DWORD;
  Data: array[0..511] of Char;
  DataLen: DWORD;
  i: Integer;

procedure DisplayCertContext(Cert: PCertContext);
var
  CertName: array[0..255] of Char;
begin
  if CertGetNameString(CertContext, CERT_NAME_EMAIL_TYPE, 0, nil,
    CertName, 256) = 0 then
    RaiseLastWin32Error;
  Writeln('Subject CERT_NAME_EMAIL_TYPE: ', CertName);
  if CertGetNameString(CertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil,
    CertName, 256) = 0 then
    RaiseLastWin32Error;
  Writeln('Subject CERT_NAME_SIMPLE_DISPLAY_TYPE: ', CertName);
  if CertGetNameString(CertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, nil,
    CertName, 256) = 0 then
    RaiseLastWin32Error;
  Writeln('Subject CERT_NAME_FRIENDLY_DISPLAY_TYPE: ', CertName);

  if CertGetNameString(CertContext, CERT_NAME_EMAIL_TYPE, CERT_NAME_ISSUER_FLAG, nil,
    CertName, 256) = 0 then
    RaiseLastWin32Error;
  Writeln('Issuer CERT_NAME_EMAIL_TYPE: ', CertName);
  if CertGetNameString(CertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, nil,
    CertName, 256) = 0 then
    RaiseLastWin32Error;
  Writeln('Issuer CERT_NAME_SIMPLE_DISPLAY_TYPE: ', CertName);
  if CertGetNameString(CertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, nil,
    CertName, 256) = 0 then
    RaiseLastWin32Error;
  Writeln('Issuer CERT_NAME_FRIENDLY_DISPLAY_TYPE: ', CertName);
end;

begin
  try
    Write('Enter name of store to be listed: ');
    Readln(StoreName);
    hStore := CertOpenSystemStore(0, StoreName);
    if hStore = nil then
      RaiseLastWin32Error;
    try
      CertContext := CertEnumCertificatesInStore(hStore, nil);
      while CertContext <> nil do
      begin
        DisplayCertContext(CertContext);
        CertPropId := CertEnumCertificateContextProperties(CertContext, 0);
        while CertPropId <> 0 do
        begin
          DataLen := 512;
  //        Writeln(Format('CertPropId: %d', [CertPropId]));
          case CertPropId of
          CERT_KEY_PROV_HANDLE_PROP_ID:
          begin
            CertGetCertificateContextProperty(CertContext, CertPropId,
              @Data[0], DataLen);
            Writeln(Format('KEY_PROV_HANDLE: $%.8x', [PDWORD(@Data[0])^]));
          end;
          CERT_KEY_PROV_INFO_PROP_ID:
          begin
            CertGetCertificateContextProperty(CertContext, CertPropId,
              @Data[0], DataLen);
            with PCryptKeyProvInfo(@Data[0])^ do
            begin
              Writeln(Format('pwszContainerName = %s', [pwszContainerName]));
              Writeln(Format('pwszProvName = %s', [pwszProvName]));
              Writeln(Format('dwFlags = %d', [dwFlags]));
              Writeln(Format('cProvParams = %d', [cProvParams]));
              //Writeln(Format('rgProvParam', [rgProvParam]));
              Writeln(Format('dwKeySpec = %d', [dwKeySpec]));
            end;
            Writeln(Format('KEY_PROV_INFO: %d', [@Data[0]]));
          end;
          CERT_FRIENDLY_NAME_PROP_ID:
          begin
            CertGetCertificateContextProperty(CertContext, CertPropId,
              @Data[0], DataLen);
            Writeln(Format('FRIENDLY_NAME: %s', [PChar(@Data[0])]));
          end;
          CERT_KEY_IDENTIFIER_PROP_ID:
          begin
            CertGetCertificateContextProperty(CertContext, CertPropId,
              @Data[0], DataLen);
            Write('KEY_IDENTIFIER: ');
            for i := 1 to DataLen do
              Write(Format('%.2x ', [PBYTE(@Data[i - 1])^]));
            Writeln;
          end;
          CERT_SHA1_HASH_PROP_ID:
          begin
            CertGetCertificateContextProperty(CertContext, CertPropId,
              @Data[0], DataLen);
            Write('SHA1_HASH: ');
            for i := 1 to DataLen do
              Write(Format('%.2x ', [PBYTE(@Data[i - 1])^]));
            Writeln;
          end;
          CERT_MD5_HASH_PROP_ID:
          begin
            CertGetCertificateContextProperty(CertContext, CertPropId,
              @Data[0], DataLen);
            Write('MD5_HASH: ');
            for i := 1 to DataLen do
              Write(Format('%.2x ', [PBYTE(@Data[i - 1])^]));
            Writeln;
          end;
          else
          end;
          CertPropId := CertEnumCertificateContextProperties(CertContext,
            CertPropId);
        end;
        CertContext := CertEnumCertificatesInStore(hStore, CertContext);
      end;
//      if GetLastError <> CRYPT_E_NOT_FOUND then
//        RaiseLastWin32Error;
    finally
      CertCloseStore(hStore, 0);
    end;
  except
    on E: Exception do
    begin
      ExitCode := 1;
      Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
    end;
  end;
end.
6 голосов
/ 17 ноября 2011

Вы можете делать что угодно с SecureBlackBox от EldoS.http://www.eldos.com/sbb/

Это программное обеспечение делает его простым.Это не легко.

4 голосов
/ 17 ноября 2011

Я рекомендую Eldos SecureBlackBox , но есть бесплатная альтернатива.

Вы также можете использовать библиотеки OpenSSL. Вам понадобится полный порт OpenSSL, так как заголовки Indy OpenSSL неполные. Вам также необходимо скомпилировать базу данных открытых сертификатов из центров сертификации, поскольку она не включена.

С OpenSSL у вас не будет доступа к хранилищу сертификатов Windows напрямую. Вы можете экспортировать сертификаты из Windows или Firefox и импортировать их.

Eldos SecureBlackBox предоставляет доступ к хранилищу сертификатов Windows, включая методы проверки подписи кода для подписи программы.

Вы можете включить двоичные файлы OpenSSL в свой продукт Windows, и OpenSSL уже установлен и доступен в Mac OS. Итак, OpenSSL жизнеспособен для FireMonkey или Lazarus.

OpenSSL довольно хорошо документирован, и вы можете найти много примеров в Интернете, хотя в основном на C или C ++. Мне повезло, что я реализовал все, что мне нужно. В нем много функций для чтения и записи в PEM-файлы.

SecureBlackBox еще не имеет версию FireMonkey, но они говорят, что у них будет одна в следующем году (согласно их форуму). У них есть fpc (бесплатная версия на паскале).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...