2011-11-17 50 views
5

Pregunta relacionada con Lazarus o Delphi. ¿Hay alguna forma de acceder mediante programación a los certificados de Autoridades de certificación raíz confiables en Windows? Sé que hay una herramienta basada en GUI en Windows llamada 'mmc.exe', pero necesito acceder a los archivos de certificado (como .crt o .cer o .pem, etc.) usando la sintaxis de Object Pascal. Alguien me puede ayudar con eso?¿Cómo puedo acceder a los certificados de las autoridades certificadoras raíz de Windows con Delphi?

Respuesta

5

Como alternativas, hay CAPICOM que puede simplemente importar como biblioteca de tipo ActiveX, pero también está el antiguo Windows Cryptography API.

Como ejemplo, aquí hay un proyecto de prueba muy antiguo (no lo he probado recientemente). Vas a necesitar la unidad WinCrypt o JwaWinCrypt con las traducciones correspondientes API que debería estar disponible en 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

Puede hacer prácticamente cualquier cosa con SecureBlackBox de EldoS. http://www.eldos.com/sbb/

Este software lo hace parecer fácil. No es fácil.

+0

Estoy de acuerdo con Chris, he tenido el privilegio de trabajar con las versiones anteriores, y que era muy bonito. Sin embargo, ya no tengo acceso a ella. Si su presupuesto lo permite, cómprelo y haga su vida más fácil. También se vuelve complicado con sus múltiples paquetes, así que hable con ellos para averiguar exactamente cuál necesita. Viene con una versión fpc. –

+1

El paquete PKIBlackBox es lo que necesita. Sin embargo, debe seguir adelante y obtener el guacamole SecureBlackBox Professional completo. No es barato (más de mil dólares) pero vale cada centavo. –

4

Recomiendo Eldos SecureBlackBox, pero hay una alternativa gratuita.

También puede usar las bibliotecas OpenSSL. Necesitará un puerto OpenSSL completo, ya que los encabezados de Indy OpenSSL están incompletos. También deberá compilar una base de datos de certificados públicos de las autoridades de certificación, ya que no está incluida.

Con OpenSSL, no tendrá acceso directamente al almacén de certificados de Windows. Puede exportar los certificados desde Windows o Firefox e importarlos.

Eldos SecureBlackBox proporciona acceso al almacén de certificados de Windows, incluidos los métodos para verificar la firma de firma de código de un programa.

Puede incluir binarios OpenSSL con su producto Windows, y OpenSSL ya está instalado y disponible en Mac OS. Entonces, OpenSSL es viable para FireMonkey o Lazarus.

OpenSSL está bastante bien documentado y puede encontrar muchos ejemplos en línea, aunque principalmente en C o C++. He tenido la suerte de implementar todo lo que necesité con él. Tiene muchas funciones para leer y escribir en archivos PEM.

SecureBlackBox aún no tiene una versión de FireMonkey, pero dicen que tendrán una el próximo año (por foro). Tienen una versión fpc (pascal libre).

Cuestiones relacionadas