2011-11-17 192 views
5

拉撒路或德尔福相关的问题。有没有办法在Windows中以编程方式访问受信任的根证书颁发机构证书。我知道Windows中有基于GUI的工具叫'mmc.exe',但我需要使用Object Pascal语法访问证书文件(如.crt或.cer或.pem等)。任何人都可以帮助我吗?如何使用Delphi访问Windows根证书颁发机构证书?

回答

5

作为替代方案,有CAPICOM,您可以简单地导入为ActiveX类型库,但也有简单的旧的Windows Cryptography API。作为一个例子,这里有一个很老的我的测试项目(我最近没试过)。你将需要WinCryptJwaWinCrypt单位与有关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

你可以通过EldoS的SecureBlackBox做任何事情。 http://www.eldos.com/sbb/

这个软件看起来很容易。这并不容易。

+0

我与克里斯同意,我已经受够了早期版本的工作的特权,这是非常不错。但是,我无法再访问它。如果你的预算允许,购买这个,让你的生活变得轻松。它们的多个软件包也变得复杂起来,所以要和他们交谈,找出你需要的是哪一个。它带有一个fpc版本。 –

+1

PKIBlackBox包是你需要的。但是,您应该继续并获得完整的SecureBlackBox Professional鳄梨酱。它并不便宜(超过一千美元),但它值得每一分钱。 –

4

我推荐Eldos SecureBlackBox,但有一个免费的替代方案。

您也可以使用OpenSSL库。由于Indy OpenSSL头文件不完整,您将需要一个完整的OpenSSL端口。您还需要从证书颁发机构编译公用证书的数据库,因为它不包含在内。

使用OpenSSL,您将无法直接访问Windows证书存储。您可以从Windows或Firefox导出证书并导入它们。

Eldos SecureBlackBox提供对Windows证书存储的访问,包括验证程序的代码签名签名的方法。

您可以在您的Windows产品中包含OpenSSL二进制文件,并且已经在Mac OS上安装并提供了OpenSSL。所以,OpenSSL对于FireMonkey或Lazarus是可行的。

OpenSSL有很好的文档记录,你可以在网上找到很多例子,尽管大多数是C或C++。我已经有很好的运气来实现我需要的任何东西。它具有很多读写PEM文件的功能。

SecureBlackBox还没有FireMonkey版本,但他们表示他们明年会有一个(每个论坛)。他们有一个fpc(免费pascal)版本。

相关问题