Tengo dos certificados autofirmados extremadamente similares, generados a través de dos métodos diferentes.
Para probarlos tengo:
- Se agregó una entrada en el archivo de mis hosts para local.mydomain.com
- Configure un servidor nginx para que escuche en ese dominio en el puerto 443 con el certificado en prueba más la clave privada asociada (a continuación, cambio el certificado y reinicio nginx para comparar)
- Conectado a nginx con
openssl s_client -connect local.mydomain.com -CAfile /path/to/the/ca/cert.pem
Un certificado falla:
CONNECTED(00000003)
depth=0 CN = local.mydomain.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = local.mydomain.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/CN=local.mydomain.com
i:/CN=local.mydomain.com
---
Un certificado tiene éxito:
CONNECTED(00000003)
depth=0 CN = local.mydomain.com
verify return:1
---
Certificate chain
0 s:/CN = local.mydomain.com
i:/CN = local.mydomain.com
---
Comparo los detalles de los certificados con openssl x509 -in /path/to/the/ca/cert.pem -text -noout
El certificado que falla:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
47:dc:02:c7:11:fc:8e:96:45:22:aa:6b:23:79:32:ca
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=local.mydomain.com
Validity
Not Before: Nov 18 11:55:31 2016 GMT
Not After : Nov 18 12:15:31 2017 GMT
Subject: CN=local.mydomain.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
<stuff>
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication, TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:local.mydomain.com
X509v3 Subject Key Identifier:
6D:4F:AF:E4:60:23:72:E5:83:27:91:7D:1D:5F:E9:7C:D9:B6:00:2A
Signature Algorithm: sha256WithRSAEncryption
<stuff>
El certificado de trabajo:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
9b:6b:3d:a3:b9:a3:a4:b4
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=local.mydomain.com
Validity
Not Before: Nov 19 13:27:30 2016 GMT
Not After : Nov 19 13:27:30 2017 GMT
Subject: CN=local.mydomain.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
<stuff>
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
03:E7:DA:AA:2E:CC:23:ED:C5:07:3D:E1:33:86:F5:22:D4:76:EB:CB
X509v3 Authority Key Identifier:
keyid:03:E7:DA:AA:2E:CC:23:ED:C5:07:3D:E1:33:86:F5:22:D4:76:EB:CB
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
57<stuff>
Mirando esto, la diferencia más obvia es que el certificado de trabajo tiene CA:TRUE
debajo de X509v3 Basic Constraints
. Sin embargo, al leer en la web tuve la impresión de que los certificados autofirmados no estaban destinados a ser CA, en particular, esto dice que normalmente no lo serán:
Preguntas básicas sobre certificados autofirmados
La respuesta dice que al autofirmarse no hay CA involucrada. Pero tal vez openssl requiere certificados autofirmados para tener ese conjunto de todos modos? ¿O tal vez los certificados difieren de alguna otra manera pertinente?
ACTUALIZACIÓN:
Pasé un tiempo tratando de imprimir y depurar las partes internas de openssl, no es que entienda nada de eso. En el archivo v3_purp.c se encuentra la siguiente macro:
#define ku_reject(x, usage) \
(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
Se utiliza en este bit de código que verifica los certificados autofirmados:
/* Does subject name match issuer ? */
if (X509_check_akid(x, x->akid) == X509_V_OK &&
!ku_reject(x, KU_KEY_CERT_SIGN))
x->ex_flags |= EXFLAG_SS;
En el caso del certificado que falla, (x)->ex_flags & EXFLAG_KUSAGE
es igual a 2
EXFLAG_KUSAGE
se configura para el certificado que falla aquí, anteriormente en el mismo archivo:
static void x509v3_cache_extensions(X509 *x)
{
......
if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
if (usage->length > 0) {
x->ex_kusage = usage->data[0];
if (usage->length > 1)
x->ex_kusage |= usage->data[1] << 8;
} else
x->ex_kusage = 0;
x->ex_flags |= EXFLAG_KUSAGE;
ASN1_BIT_STRING_free(usage);
}
....
Parece que el problema es que el certificado que falla tiene la extensión X509v3 Key Usage
, pero no especifica KU_KEY_CERT_SIGN en esa extensión?
ACTUALIZACIÓN 2:
Según enlace :
"El bit keyCertSign se afirma cuando se utiliza la clave pública del sujeto Para la verificación de firmas en certificados de clave pública. Si el Se afirma el bit keyCertSign, luego el bit cA en las restricciones básicas la extensión (Sección 4.2.1.9) DEBE ser declarada ".
Por lo tanto, el bit CA en las restricciones básicas no tiene por qué estar presente, pero si incluye una sección de Uso de claves X509v3 en el certificado, entonces de acuerdo con la base de código de openssl, debe especificar keyCertSign, y de acuerdo con el RFC si especifica keyCertSign También debe incluir las restricciones básicas de bits de CA.