2012-02-29 13 views
25

Algunos códigos de C++ en funcionamiento que estoy portando de Linux a Windows fallan en Windows porque SSL_get_verify_result() está devolviendo X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY.¿Puede OpenSSL en Windows usar el almacén de certificados del sistema?

El código estaba usando SSL_CTX_set_default_verify_paths() en Linux para indicar a SSL que simplemente busque en las ubicaciones predeterminadas estándar para el almacén de certificados.

¿Es posible hacer que OpenSSL use el almacén de certificados del sistema?

Respuesta

34

Lo he hecho antes. Espero que esto ayude, si esto es exactamente lo que está buscando.

  1. Cargue su certificado (en la estructura PCCERT_CONTEXT) de la tienda Cert de Windows utilizando las API Crypto.
  2. Obtenga el contenido cifrado en formato binario como está. [PCCERT_CONTEXT->pbCertEncoded].
  3. Analice este búfer binario en el objeto del certificado X509 utilizando el método d2i_X509() de OpenSSL.
  4. Acceda al almacén de confianza de OpenSSL utilizando el método SSL_CTX_get_cert_store().
  5. Cargue el certificado X509 analizado en esta tienda de confianza utilizando el método X509_STORE_add_cert().
  6. ¡Ya ha terminado!
+0

Gracias por la información. Debo añadir algunas notas sobre esto: 1. enum Windows's store con "ROOT" (no "CA"). 2. Debe agregar el cert antes de la conexión/handshake, y verificar luego de la conexión/handshake, de lo contrario la verificación fallará. –

2

No. No está fuera de la caja.

No, es no es posible fuera de la caja. Requeriría programación adicional. Con OpenSSL tiene dos (de la caja) Opciones:

    propia tienda cert
  1. del uso de OpenSSL (se trata de una jerarquía de directorios creados por script de perl provisto con OpenSSL)
  2. Use sólo un archivo de cadena de certificado creado por usted (es un archivo de texto con todos los certificados con codificación PEM en una cadena de confianza). Crear un archivo de este tipo es fácil (simplemente adjuntándolo)
+0

¿Sería posible crear un archivo PEM en la memoria de las ventanas archivos pkcs? Entonces carga eso? Encontré: http://marc.info/?l=openssl-users&m=119583966725315 que describe la creación de un archivo PEM a partir de los paquetes de pkcs ... Y http://stackoverflow.com/questions/5052563/c-openssl-use -root-ca-from-buffer-rather-file-ssl-ctx-load-verify-locat describe un mecanismo para cargar un archivo PEM desde un buffer ...? – dicroce

+0

Sí, eso es ciertamente posible. – sirgeorge

+0

Yuck ... Por alguna razón, no le gusta mi archivo (hecho con el código de esa página) ... ¿Hubiera pensado que alguien antes que yo habría hecho esto? – dicroce

2

Es posible utilizar OpenSSL para la operación como de costumbre, y utilizar CryptoAPI sólo para el proceso de verificación del certificado. Veo varios hilos por aquí sobre este tema, y ​​la mayoría están de puntillas alrededor.

Con CryptoAPI usted tiene que:

  • decodificación PEM a DER con CryptStringToBinary(),
  • crear un objeto CERT_CONTEXT con CertCreateCertificateContext()
  • y verificar el certificado en esta forma por el procedimiento documentado bien conocido /. (Por ejemplo here at ETutorials.)

    Por último paso para trabajar, también es necesario para inicializar HCERTSTORE para uno de MY, ROOT, CA sistema almacena, o se puede recorrer a través de ellos ... en función del comportamiento que desea.

10

Para aquellos que todavía estén luchando con esto ya que he estado, he aquí un ejemplo de código para empezar:

#include <stdio.h> 
#include <windows.h> 
#include <wincrypt.h> 
#include <cryptuiapi.h> 
#include <iostream> 
#include <tchar.h> 

#include "openssl\x509.h" 

#pragma comment (lib, "crypt32.lib") 
#pragma comment (lib, "cryptui.lib") 

#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) 

int main(void) 
{ 
    HCERTSTORE hStore; 
    PCCERT_CONTEXT pContext = NULL; 
    X509 *x509; 
    X509_STORE *store = X509_STORE_new(); 

    hStore = CertOpenSystemStore(NULL, L"ROOT"); 

    if (!hStore) 
     return 1; 

    while (pContext = CertEnumCertificatesInStore(hStore, pContext)) 
    { 
     //uncomment the line below if you want to see the certificates as pop ups 
     //CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pContext, NULL, NULL, 0, NULL); 

     x509 = NULL; 
     x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded); 
     if (x509) 
     { 
      int i = X509_STORE_add_cert(store, x509); 

      if (i == 1) 
       std::cout << "certificate added" << std::endl; 

      X509_free(x509); 
     } 
    } 

CertFreeCertificateContext(pContext); 
CertCloseStore(hStore, 0); 
system("pause"); 
return 0; 

} 
+1

Su uso de 'd2i_X509' no es válido porque' d2i_X509' incrementa el argumento '* in' (usa el molde para evitar el error del compilador). Debe usar una variable temp para evitar problemas de memoria, como este: 'const unsigned char * encoded_cert = win_cert_context-> pbCertEncoded; d2i_X509 (nullptr, y encoded_cert, ... ' – herolover

Cuestiones relacionadas