Ho due certificati autofirmati estremamente simili, generati con due metodi diversi.
Per testarli ho:
- Aggiunta una voce nel mio file hosts per local.mydomain.com
- Configura un server nginx per l'ascolto su quel dominio sulla porta 443 con il certificato in prova più la chiave privata associata (quindi, cambio il certificato e riavvia il nginx per il confronto)
- Connesso a nginx con
openssl s_client -connect local.mydomain.com -CAfile /path/to/the/ca/cert.pem
Un certificato fallisce:
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 certificato ha esito positivo:
CONNECTED(00000003)
depth=0 CN = local.mydomain.com
verify return:1
---
Certificate chain
0 s:/CN = local.mydomain.com
i:/CN = local.mydomain.com
---
Confronto i dettagli dei certificati con openssl x509 -in /path/to/the/ca/cert.pem -text -noout
Il certificato fallito:
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>
Il certificato di lavoro:
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>
Guardando a questo la differenza più ovvia è che il certificato di lavoro ha CA:TRUE
sotto X509v3 Basic Constraints
. Tuttavia, dalla lettura sul Web avevo l'impressione che i certificati autofirmati non dovessero essere CA, in particolare questo dice che normalmente non saranno:
Domande di certificato autofirmato di base
La risposta là dice che essendo autofirmati non c'è nessuna CA coinvolta. Ma forse openssl richiede cerattori autofirmati per avere quel set comunque? O forse i certificati differiscono in qualche altro modo pertinente?
UPDATE:
Ho passato un po 'di tempo a provare a printf eseguire il debug degli interni di openssl, non che ne capisca niente. Nel file v3_purp.c è presente la seguente macro:
#define ku_reject(x, usage) \
(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
Viene utilizzato in questo bit di codice che controlla i certificati autofirmati:
/* 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;
Nel caso del certificato fallito (x)->ex_flags & EXFLAG_KUSAGE
è uguale a 2
EXFLAG_KUSAGE
viene impostato per il certificato in errore qui, prima nello stesso file:
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);
}
....
Quindi sembra che il problema è che il certificato fallito ha l'estensione X509v3 Key Usage
, ma non specifica KU_KEY_CERT_SIGN in quell'estensione?
UPDATE 2:
In base al link :
"The keyCertSign bit is asserted when the subject public key is used for verifying signatures on public key certificates. If the keyCertSign bit is asserted, then the cA bit in the basic constraints extension (Section 4.2.1.9) MUST also be asserted."
Quindi il bit CA nei vincoli di base non deve essere presente, ma se si include una sezione Utilizzo chiave X509v3 nel certificato, in base al codice openssl, è necessario specificare keyCertSign e, in base a RFC, specificare keyCertSign, quindi devi anche includere i vincoli di base del bit CA?