Esto es muy similar a otras preguntas, pero de los que he mirado no tienen una respuesta o no la misma pregunta. Tengo un auto firmado el certificado de CA, y otros dos certificados que están firmados con certificado de la CA. Estoy bastante seguro de que los certificados son correctos, porque » openssl verificar las obras:

$ openssl verify -CAfile ca.pem server.pem
server.pem: OK

(La de arriba es de memoria, no los tengo en frente de mí, así que puede ser un poco off).

Ahora quiero verificar los certificados en forma programática. Tengo una función de utilidad con pseudocódigo a continuación:

int verify_cert(X509 *cert, X509 *cacert)
{
     int ret;
     X509_STORE *store;
     X509_STORE_CTX *ctx;

     store = X509_STORE_new();
     X590_STORE_add_cert(store, cacert);

     ctx = X509_STORE_CTX_new();
     X509_STORE_CTX_init(ctx, store, cert, NULL);

     ret = X590_verify_cert(ctx);

     /* check for errors and clean up */
}

Mi problema es que el código de arriba siempre devuelve ‘no se pudo encontrar el emisor del certificado. ¿Qué he hecho mal? Creo que me estoy creando una nueva tienda, añadir el cacert, la creación de un nuevo contexto, y añadiendo el niño cert ser verificada para el contexto con un puntero a la tienda que contiene la CA. Estoy bastante obviamente haciendo algo mal, pero estoy seguro de qué.

Alguna idea?

Actualización: soy consciente de que puedo guardar estos certificados en el disco y usar algo como X509_LOOKUP_file o algo similar. Estoy buscando una solución que no toque el disco innecesariamente.

  • Im que enfrentan el mismo problema – ¿encontraste alguna solución?
  • no, lamentablemente no. La he puesto en un segundo plano por ahora y concentrarse en otras cosas. Todavía estoy en busca de una respuesta aquí.
  • posibles duplicados de certificado x509 de verificación en C
  • Esto no es un duplicado, el vinculado pregunta no utilizar en memoria de los certs y en la memoria del almacén de certificados. Esto hace.
  • si este es un año demasiado tarde para ayudar!) Estoy usando esencialmente idéntico código en nuestra aplicación comercial que utiliza un circuito cerrado de CA del sistema. Esto funciona para nosotros! Algo que nos sorprendió es de OpenSSL comprobación de extensiones de certificado; tal vez X509_STORE_CTX_set_purpose(X509_PURPOSE_ANY) le ayudará si está estancado debido a su CA cert no tiene una de las extensiones de uso público CAs uso? Aparte de que estoy usando literalmente código idéntico al tuyo y funciona, por lo que la diferencia debe estar en la forma en que estoy generando los certificados en comparación con usted.
  • Consulte este enlace: openssl.6102.n7.nabble.com/… que parece Que uno necesita llamar «OpenSSL_add_all_algorithms()».

InformationsquelleAutor clemej | 2013-04-30

5 Comentarios

  1. 14

    Puede utilizar la normal rutinas de validación (ver ¿Cómo se puede verificar que una clave pública emitido por privado CA?), como la función verify en OpenSSL hace. Usted necesita para crear un método de búsqueda (X509_LOOKUP_METHOD) como X509_LOOKUP_file(), sino que trabaja con una cadena de caracteres en lugar de un nombre de archivo. El código para X509_LOOKUP_buffer() es la siguiente.

    Archivo de encabezado by_buffer.h:

    /* File:   by_buffer.h */
    
    #ifndef BY_BUFFER_H
    #define    BY_BUFFER_H
    
    #include <openssl/x509.h>
    
    #ifdef    __cplusplus
    extern "C" {
    #endif
    #define X509_L_BUF_LOAD    1
    #define X509_LOOKUP_load_buf(x,name,type) \
            X509_LOOKUP_ctrl((x),X509_L_BUF_LOAD,(name),(long)(type),NULL)
    X509_LOOKUP_METHOD *X509_LOOKUP_buffer(void);
    
    #ifdef    __cplusplus
    }
    #endif
    
    #endif    /* BY_BUFFER_H */

    El programa de c by_buffer.c:

    /* by_buffer.c - copied and modified from crypto/x509/by_file.c */
    /* Copyright (C) - should be the same as for OpenSSL
    */
    #include "by_buffer.h"
    #include <stdio.h>
    #include <time.h>
    #include <errno.h>
    #include "../crypto/cryptlib.h"
    #include <openssl/lhash.h>
    #include <openssl/buffer.h>
    #include <openssl/pem.h>
    #include <openssl/err.h>
    static int by_buffer_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
    long argl, char **ret);
    X509_LOOKUP_METHOD x509_buffer_lookup=
    {
    "Load buffer into cache",
    NULL,        /* new */
    NULL,        /* free */
    NULL,         /* init */
    NULL,        /* shutdown */
    by_buffer_ctrl,    /* ctrl */
    NULL,        /* get_by_subject */
    NULL,        /* get_by_issuer_serial */
    NULL,        /* get_by_fingerprint */
    NULL,        /* get_by_alias */
    };
    X509_LOOKUP_METHOD *X509_LOOKUP_buffer(void)
    {
    return(&x509_buffer_lookup);
    }
    static int by_buffer_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
    char **ret)
    {
    int ok=0;
    char *certBuf;
    switch (cmd)
    {
    case X509_L_BUF_LOAD:
    if (argl == X509_FILETYPE_DEFAULT)
    {
    X509err(X509_F_BY_FILE_CTRL,X509_R_LOADING_DEFAULTS);
    }
    else
    {
    if(argl == X509_FILETYPE_PEM)
    ok = (X509_load_cert_crl_buf(ctx,argp,
    X509_FILETYPE_PEM) != 0);
    else
    ok = (X509_load_cert_buf(ctx,argp,(int)argl) != 0);
    }
    break;
    }
    return(ok);
    }
    int X509_load_cert_buf(X509_LOOKUP *ctx, const char *certBuf, int type)
    {
    int ret=0;
    BIO *in=NULL;
    int i,count=0;
    X509 *x=NULL;
    if (certBuf == NULL) return(1);
    in=BIO_new(BIO_s_mem());
    if(in==NULL) goto err;
    if (type == X509_FILETYPE_PEM)
    {
    for (;;)
    {
    x=PEM_read_bio_X509_AUX(in,NULL,NULL,NULL);
    if (x == NULL)
    {
    if ((ERR_GET_REASON(ERR_peek_last_error()) ==
    PEM_R_NO_START_LINE) && (count > 0))
    {
    ERR_clear_error();
    break;
    }
    else
    {
    X509err(X509_F_X509_LOAD_CERT_FILE,
    ERR_R_PEM_LIB);
    goto err;
    }
    }
    i=X509_STORE_add_cert(ctx->store_ctx,x);
    if (!i) goto err;
    count++;
    X509_free(x);
    x=NULL;
    }
    ret=count;
    }
    else if (type == X509_FILETYPE_ASN1)
    {
    x=d2i_X509_bio(in,NULL);
    if (x == NULL)
    {
    X509err(X509_F_X509_LOAD_CERT_FILE,ERR_R_ASN1_LIB);
    goto err;
    }
    i=X509_STORE_add_cert(ctx->store_ctx,x);
    if (!i) goto err;
    ret=i;
    }
    else
    {
    X509err(X509_F_X509_LOAD_CERT_FILE,X509_R_BAD_X509_FILETYPE);
    goto err;
    }
    err:
    if (x != NULL) X509_free(x);
    if (in != NULL) BIO_free(in);
    return(ret);
    }
    int X509_load_crl_buf(X509_LOOKUP *ctx, const char *certBuf, int type)
    {
    int ret=0;
    BIO *in=NULL;
    int i,count=0;
    X509_CRL *x=NULL;
    if (certBuf == NULL) return(1);
    //in=BIO_new(BIO_s_file_internal());
    in=BIO_new(BIO_s_mem());
    if(in==NULL) goto err;
    if (type == X509_FILETYPE_PEM)
    {
    for (;;)
    {
    x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
    if (x == NULL)
    {
    if ((ERR_GET_REASON(ERR_peek_last_error()) ==
    PEM_R_NO_START_LINE) && (count > 0))
    {
    ERR_clear_error();
    break;
    }
    else
    {
    X509err(X509_F_X509_LOAD_CRL_FILE,
    ERR_R_PEM_LIB);
    goto err;
    }
    }
    i=X509_STORE_add_crl(ctx->store_ctx,x);
    if (!i) goto err;
    count++;
    X509_CRL_free(x);
    x=NULL;
    }
    ret=count;
    }
    else if (type == X509_FILETYPE_ASN1)
    {
    x=d2i_X509_CRL_bio(in,NULL);
    if (x == NULL)
    {
    X509err(X509_F_X509_LOAD_CRL_FILE,ERR_R_ASN1_LIB);
    goto err;
    }
    i=X509_STORE_add_crl(ctx->store_ctx,x);
    if (!i) goto err;
    ret=i;
    }
    else
    {
    X509err(X509_F_X509_LOAD_CRL_FILE,X509_R_BAD_X509_FILETYPE);
    goto err;
    }
    err:
    if (x != NULL) X509_CRL_free(x);
    if (in != NULL) BIO_free(in);
    return(ret);
    }
    int X509_load_cert_crl_buf(X509_LOOKUP *ctx, const char *certBuf, int type)
    {
    STACK_OF(X509_INFO) *inf;
    X509_INFO *itmp;
    BIO *in;
    int i, count = 0;
    if(type != X509_FILETYPE_PEM)
    return X509_load_cert_buf(ctx, certBuf, type);
    in = BIO_new(BIO_s_mem());
    if(!in) {
    X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_SYS_LIB);
    return 0;
    }
    BIO_write(in, certBuf, strlen(certBuf));
    inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
    BIO_free(in);
    if(!inf) {
    X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_PEM_LIB);
    return 0;
    }
    for(i = 0; i < sk_X509_INFO_num(inf); i++) {
    itmp = sk_X509_INFO_value(inf, i);
    if(itmp->x509) {
    X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
    count++;
    }
    if(itmp->crl) {
    X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
    count++;
    }
    }
    sk_X509_INFO_pop_free(inf, X509_INFO_free);
    return count;
    }

    Rutina en C++, que llama a la anterior rutinas:

    #include "by_buffer.h"
    static int check(X509_STORE *ctx, const char *certBuf);
    static X509 *load_cert(const char *certBuf);
    int validateKey(const char *rsaKeyCA, const char *rsaCertificate) {
    int ret=0;
    X509_STORE *cert_ctx=NULL;
    X509_LOOKUP *lookup=NULL;
    cert_ctx=X509_STORE_new();
    if (cert_ctx == NULL) goto end;
    OpenSSL_add_all_algorithms();
    lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_buffer());
    if (lookup == NULL)
    goto end;
    if(!X509_LOOKUP_load_buf(lookup,rsaKeyCA,X509_FILETYPE_PEM))
    goto end;
    lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_hash_dir());
    if (lookup == NULL)
    goto end;
    X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
    ret = check(cert_ctx, rsaCertificate);
    end:
    if (cert_ctx != NULL) X509_STORE_free(cert_ctx);
    return ret;
    }
    static X509 *load_cert(const char *certBuf)
    {
    X509 *x=NULL;
    BIO *cert;
    if ((cert=BIO_new(BIO_s_mem())) == NULL)
    goto end;
    BIO_write(cert, certBuf, strlen(certBuf));
    x=PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL);
    end:
    if (cert != NULL) BIO_free(cert);
    return(x);
    }
    static int check(X509_STORE *ctx, const char *certBuf)
    {
    X509 *x=NULL;
    int i=0,ret=0;
    X509_STORE_CTX *csc;
    x = load_cert(certBuf);
    if (x == NULL)
    goto end;
    csc = X509_STORE_CTX_new();
    if (csc == NULL)
    goto end;
    X509_STORE_set_flags(ctx, 0);
    if(!X509_STORE_CTX_init(csc,ctx,x,0))
    goto end;
    //////See crypto/asn1/t_x509.c for ideas on how to access and print the values
    //printf("X.509 name: %s\n", x->name);
    i=X509_verify_cert(csc);
    X509_STORE_CTX_free(csc);
    ret=0;
    end:
    ret = (i > 0);
    if (x != NULL)
    X509_free(x);
    return(ret);
    }
    • Eso es un montón de trabajo para definir un nuevo mecanismo de devolución de llamada. Pero también parece ser el único camino. Puntos de bonificación para la gran ejemplo de código.
    • Este código es «correcto» pero todo es completamente inútil! La llamada central en este código es X509_STORE_add_cert, que es exactamente la misma llamada a la API de que el OP fue originalmente usando. Se ha envuelto a pesar de que en los montones de ofuscación de los potingues por ocultarlo dentro de la X509_load_cert_buf función, a continuación, llamar a que en una muy forma indirecta mediante X509_LOOKUP_load_buf. Este código no ofrece ninguna ventaja en todo el OP del código original que simplemente se llama X509_STORE_add_cert directamente.
    • Lo siento que yo siempre «inútil» código! Lo que yo quería hacer era duplicar el openssl función verify, que trabaja, como lo hace MI código. No he hecho el intento de optimizar mejor que el código de OpenSSL.
  2. 4

    Me encontré con este problema mí y comenzó con código muy cerca de la OP. Mi certificado incluye cadena 3 certificados:
    Certificado 1 (raíz-ca) Emisor: a la raíz ca Asunto: raíz-ca
    Certificado 2 (firma-ca) Emisor: a la raíz ca Asunto: firma-ca
    Certificado 3 (dispositivo) Emisor: la firma-ca Asunto: dispositivo

    Quería comprobar el certificado del dispositivo. Mi ca.pem equivalente (wrt OP) que contiene la raíz-ca y la firma-ca.

    La X509_verify_cert función de las necesidades de toda la cadena de certificados en todo el camino hasta la raíz (root-ca & firma-ca) en el X509_store.

    A continuación es mi código que me funciona. Comprueba en los valores de retorno se han omitido para que lean el código de abajo.

    int getIssuerCert(X509_STORE *x509_store){
    STACK_OF(X509_INFO) *inf;
    X509_INFO *itmp;
    BIO *in;
    int i, count = 0;
    in = BIO_new(BIO_s_mem());
    BIO_write(in, issuerCertStr, strlen(issuerCertStr)); //string containing root-ca & signing-ca
    inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
    if(in != NULL) BIO_free(in);
    for(i = 0; i < sk_X509_INFO_num(inf); i++) {
    itmp = sk_X509_INFO_value(inf, i);
    if(itmp->x509) {
    X509_STORE_add_cert(x509_store, itmp->x509);
    count++;
    }
    if(itmp->crl) {
    X509_STORE_add_crl(x509_store, itmp->crl);
    count++;
    }
    }
    sk_X509_INFO_pop_free(inf, X509_INFO_free);
    return 0;
    }
    int verify_cert(){
    int ret = 0;
    X509 *devCert = NULL;
    X509_STORE *x509_store = NULL;
    X509_STORE_CTX *x509_store_ctx = NULL;
    OpenSSL_add_all_algorithms();
    devCert = getDeviceCert(); // Returns X509 pointer
    x509_store = X509_STORE_new();
    X509_STORE_set_verify_cb(x509_store, verify_cb);
    X509_STORE_set_flags(x509_store, 0);
    x509_store_ctx = X509_STORE_CTX_new();
    X509_STORE_CTX_init(x509_store_ctx, x509_store, devCert, NULL)
    X509_STORE_CTX_set_purpose(x509_store_ctx, X509_PURPOSE_ANY);
    ret = X509_verify_cert(x509_store_ctx);
    if(x509_store_ctx != NULL) X509_STORE_CTX_free(x509_store_ctx);
    if(x509_store != NULL) X509_STORE_free(x509_store);
    if(devCert != NULL) X509_free(devCert);
    EVP_cleanup();
    return ret;
    }

    No tenía la necesidad de crear métodos de búsqueda. La clave para mí fue un bucle a través de mis certificados de la cadena en la memoria por lo que tuve todos los certificados que necesite para completar la cadena. La cadena es equivalente a lo que habría alimentado en openssl para verificar la opción -CAfile.

    También, asegúrese de que su X509 punteros no son nulos cuando se utilizan.

  3. 3

    Un posible respuesta (no tienen la rep puntos para agregar un comentario, lo siento): la página del manual para SSL_CTX_load_verify_locations(3) dice,

    When building its own certificate chain, an OpenSSL client/server will try to fill in
    missing certificates from CAfile/CApath, if the certificate chain was not explicitly
    specified (see SSL_CTX_add_extra_chain_cert(3), SSL_CTX_use_certificate(3).

    (Falta de coincidencia paréntesis el suyo, no el mío.)

    Que parece significar que, como alternativa a la SSL_CTX_load_verify_locations(3), debería ser posible utilizar SSL_CTX_add_extra_chain_cert(3) o SSL_CTX_use_certificate(3) — ambos de los cuales un X509 * arg. Obviando así la necesidad de Mr Ed la solución como se ha visto anteriormente.

  4. 2

    Por favor, eche un vistazo a SSL_CTX_load_verify_locations () función: http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html

    SSL_CTX_load_verify_locations() especifica las ubicaciones para ctx, en
    que CA certificados para fines de verificación se encuentran. El
    certificados disponibles a través de CAfile y CApath son de confianza.

    Puede generar un certificado de CA archivo que contiene ambos, ca.pem servidor.pem:

     #!/bin/sh
    rm CAfile.pem
    for i in ca.pem server.pem ; do
    openssl x509 -in $i -text >> CAfile.pem
    done

    Y, a continuación, establezca CAfile variable a punto para CAfile.pem archivo.

    Espero que ayude !

    • Estoy confundido, ¿por qué necesitaría para especificar una ubicación de archivos (o directorios) cuando estoy carga de los certificados de forma explícita el uso de add_cert?
    • He podido encontrar ninguna X590_STORE_add_cert () en función de OpenSSL, ¿de dónde provienen? Por lo general, usted desea utilizar SSL_CTX_load_verify_locations () la función con una ruta de archivo PEM para verificar la cadena de certificados.
    • umich.edu/~x509/ssleay/x509_store.html . Pero aquí está el problema. Estos archivos no están en el disco. Ya están en la memoria de x509 estructuras. Realmente no debería necesidad de escribirlos en el disco para verificar con ellos .. ¿qué hago?
    • hey, ¿qué es SSleay ? OpenSSL dice que es «el antepasado paquete de OpenSSL», ¿por qué usarlo ? Realmente depende de cómo obtener estos certificados, si están ubicados en el disco, a continuación, utilizar la función que he publicado anteriormente, vamos a hacer el trabajo. si desea comprobar un certificado de servidor, entonces este es un problema diferente.
    • Yo no estoy usando ssleay, pero las funciones son las mismas y que el mayor éxito en Google. Gracias por tomarse el tiempo de responder, pero realmente me gustaría prefieren una solución que no implique tocar el disco.
  5. 2

    Creo, puede utilizar «X509_STORE_set_verify_cb» para agregar una devolución de llamada para identificar el error real:

    static int  verify_cb(int ok, X509_STORE_CTX *ctx)
    {
    if (!ok)
    {
    /* check the error code and current cert*/
    X509 *currentCert = X509_STORE_CTX_get_current_cert(ctx);
    int certError = X509_STORE_CTX_get_error(ctx);
    int depth = X509_STORE_CTX_get_error_depth(ctx);
    printCert(currentCert);
    printf("Error depth %d, certError %d", depth, certError)
    }
    return(ok);
    }
    int verify_cert(X509 *cert, X509 *cacert)
    {
    int ret;
    X509_STORE *store;
    X509_STORE_CTX *ctx;
    store = X509_STORE_new();
    X509_STORE_set_verify_cb(store, verify_cb);
    X590_STORE_add_cert(store, cacert);
    ctx = X509_STORE_CTX_new();
    X509_STORE_CTX_init(ctx, store, cert, NULL);
    ret = X590_verify_cert(ctx);
    /* check for errors and clean up */
    }

    A menos que saber el código de error es difícil adivinar que el problema real. El código de lo contrario, se ve bien.

Dejar respuesta

Please enter your comment!
Please enter your name here