2011-11-17 1 views
5

나사로 또는 델파이 관련 질문. 프로그래밍 방식으로 Windows의 신뢰할 수있는 루트 인증 기관 인증서에 액세스하는 방법이 있습니까? 나는 GUI에서 'mmc.exe'라고 불리는 GUI 기반 도구를 알고 있지만 오브젝트 파스칼 구문을 사용하여 인증서 파일 (예 : .crt 또는 .cer 또는 .pem 등)에 액세스해야합니다. 누구든지 저를 도울 수 있습니까?어떻게하면 Windows 루트 인증 기관 인증서에 Delphi로 액세스 할 수 있습니까?

답변

5

대체 방법으로는 ActiveX 형식 라이브러리로 가져올 수있는 CAPICOM이 있지만 일반 오래된 Windows Cryptography API도 있습니다.

예를 들어, 여기 매우 오래된 광산 테스트 프로젝트입니다 (최근에 시도하지는 않았습니다). 당신은 JEDI에 사용할 수 있어야합니다 관련 API 번역과 WinCrypt 또는 JwaWinCrypt 장치 필요 해요 : 내가 크리스 동의

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 바이너리를 포함 할 수 있으며 OpenSSL이 이미 설치되어 Mac OS에서 사용할 수 있습니다. 따라서 OpenSSL은 FireMonkey 또는 Lazarus에서 실행 가능합니다.

OpenSSL은 문서화가 잘되어있어 대부분 C 또는 C++에서 온라인으로 많은 예제를 찾을 수 있습니다. 나는 그것으로 필요한 무엇이라도 구현하는 행운을 빕니다. 그것은 PEM 파일을 읽고 쓸 수있는 많은 기능을 가지고 있습니다.

SecureBlackBox에는 아직 FireMonkey 버전이 없지만 내년에는 (포럼 당) 1 년이 소요될 것이라고합니다. 그들에는 fpc (자유로운 파스칼) 버전이있다.

관련 문제