Verificación del certificado x509 en C

4 minutos de lectura

avatar de usuario
abresid

Tengo certificados en formato DER y PEM, mi objetivo es recuperar los campos de Emisor y Asunto y verificar el certificado con la clave pública de CA y simultáneamente verificar el certificado de CA con la clave pública raíz. Puedo recuperar todos los detalles del emisor y el sujeto, pero no puedo verificar el certificado.
La API utilizada:

x509 = d2i_X509_fp (fp, &x509); //READING DER Format
x509 = PEM_read_X509 (fp, &x509, NULL, NULL); //READING PEM Format
//to retrieve the Subject:
X509_NAME_oneline(X509_get_subject_name(x509), subject, sizeof (subject));
//to retrieve the Issuer:
X509_NAME_oneline(X509_get_issuer_name(x509), issuer, sizeof (issuer));

//To store the CA public key (in unsigned char *key) that will be used to verify the 
//certificate (in my case always sha1WithRSAEncryption):
RSA *x = X509_get_pubkey(x509)->pkey.rsa;
bn = x->n;
//extracts the bytes from public key & convert into unsigned char buffer
buf_len = (size_t) BN_num_bytes (bn);
stored_CA_pubKey = (unsigned char *)malloc (buf_len);
i_n = BN_bn2bin (bn, (unsigned char *)stored_CA_pubKey);
if (i_n != buf_len)
  LOG(ERROR," : key error\n");
if (key[0] & 0x80)
  LOG(DEBUG, "00\n");

stored_CA_pubKeyLen = EVP_PKEY_size(X509_get_pubkey(x509));

Para la verificación, pasé por diferentes enfoques, pero no puedo verificar:

a)

i_x509_verify = X509_verify(cert_x509, ca_pubkey);

B)

/* verify the signature */
int iRet1, iRet2, iReason;
iRet1 = EVP_VerifyInit(&md_ctx, EVP_sha1());
iRet2 = EVP_VerifyUpdate(&md_ctx, cert_code, cert_code_len);
rv = EVP_VerifyFinal(&md_ctx, (const unsigned char *)stored_CA_pubKey,
     stored_CA_pubKeyLen, cert_pubkey);

NOTA: cert_code y stored_CA_pubKey son búferes de caracteres sin firmar.

avatar de usuario
fagi

Uso el siguiente código para verificar un certificado.

init Almacén de certificados:

X509_STORE* m_store = X509_STORE_new();
X509_LOOKUP* m_lookup = X509_STORE_add_lookup(m_store,X509_LOOKUP_file());    
X509_STORE_load_locations(m_store, "CAFile.pem", NULL);
X509_STORE_set_default_paths(m_store);
X509_LOOKUP_load_file(m_lookup,"CAFile.pem",X509_FILETYPE_PEM)
// alternative lookup by hashdir
// X509_LOOKUP* m_lookup=X509_STORE_add_lookup(m_store,X509_LOOKUP_hash_dir());

VerificarCert:

X509_STORE_CTX *storeCtx = X509_STORE_CTX_new();
X509_STORE_CTX_init(storeCtx,m_store,cert,NULL);
X509_STORE_CTX_set_flags(storeCtx, X509_V_FLAG_CB_ISSUER_CHECK);
if (X509_verify_cert(storeCtx) == 1)
{
  printf("success");
}
else
{
  printf("Verificatione rror: %s",X509_verify_cert_error_string(storeCtx->error));
}
X509_STORE_CTX_free(storeCtx);

también necesitas limpiar m_store

if(m_store != NULL)
{
   X509_STORE_free(m_store);
   m_store = NULL;
}

  • en init cert store, se usa llookup de 2 líneas, pero se declara en la 5ª línea… ¿cómo funciona este código? por favor dar el código completo

    – Balamurugan

    19 de julio de 2011 a las 15:22

  • Gracias Balamurugan, copié solo las partes relevantes del código, el código completo sería demasiado complejo. 🙂 El segundo inicio de búsqueda es una alternativa en la que los archivos ca se almacenan en un directorio hash.

    – pHagi

    9 de diciembre de 2013 a las 10:02

  • Deberías usar X509_STORE_CTX_get_error(storeCtx) en lugar de storeCtx->error; este último es más frágil debido a cambios en el ABI.

    – Jake Petroules

    16 de noviembre de 2016 a las 21:46

avatar de usuario
Juan

Eche un vistazo a mi pregunta auto respondida: https://stackoverflow.com/questions/3412032/openssl-c-how-do-you-verify-a-public-key-was-issued-by-your-private- ca va un largo camino para hacer lo que necesita.

X509_STORE* m_store = NULL;

X509_LOOKUP *m_lookup = NULL;
X509_STORE_CTX *storeCtx = NULL;
m_store = X509_STORE_new();
if(NULL == m_store) goto exit;
m_lookup = X509_STORE_add_lookup(m_store, X509_LOOKUP_file());
if(NULL == m_lookup) goto exit;
X509_STORE_load_locations(m_store, CA_CERT_PATH, NULL);
X509_STORE_set_default_paths(m_store);
X509_LOOKUP_load_file(m_lookup,CA_CERT_PATH, X509_FILETYPE_ASN1);
m_lookup = X509_STORE_add_lookup(m_store, X509_LOOKUP_hash_dir());
if(NULL == m_lookup) goto exit;
storeCtx = X509_STORE_CTX_new();
if(NULL == storeCtx) goto exit;
X509_STORE_CTX_init(storeCtx,m_store,cer_x509,NULL);
X509_STORE_CTX_set_flags(storeCtx, /*X509_V_FLAG_CHECK_SS_SIGNATURE*/0x4000);
if (X509_verify_cert(storeCtx) == 1)
{
printf("success\n");
}
else
{
printf("Verification error: %s\n",X509_verify_cert_error_string(storeCtx->error));
}
exit:
    if(NULL != storeCtx) X509_STORE_CTX_free(storeCtx);
    if(m_store != NULL)
    {
        X509_STORE_free(m_store);
        m_store = NULL;
    }

Después de hacer esto, tampoco puedo verificar el certificado autofirmado

  • He intentado algo similar, pero la verificación del certificado autofirmado no funciona. Incluso instalé manualmente el certificado en mi máquina usando el complemento “Administrar certificados de computadora”. Cualquier ayuda sería apreciada. X509_STORE_CTX* ctx; ctx = X509_STORE_CTX_nuevo(); X509_STORE* tienda = X509_STORE_new(); X509_STORE_add_cert(tienda, certificado); X509_STORE_CTX_init(ctx, tienda, certificado, NULL); X509_VERIFY_PARAM* parámetro = NULL; parámetro = X509_VERIFY_PARAM_new(); si (param) {X509_VERIFY_PARAM_set_flags(param,X509_V_FLAG_CHECK_SS_SIGNATURE);} estado = X509_verify_cert(ctx);

    -Arjun Natarajan

    14/09/2021 a las 11:40

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad