2011-11-17 199 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)版本。

相關問題