Erreur OpenSSL - impossible d'obtenir le certificat d'émetteur local
J'ai une configuration de chaîne simple et je peux vérifier avec succès dans ce cas:
$ openssl version
OpenSSL 1.0.2m 2 Nov 2017
$ openssl verify -CAfile chain.pem cert.pem
cert.pem: OK
Cependant, j'obtiens des erreurs dans ces cas:
$ openssl verify -CAfile ca-cert.pem cert.pem
cert.pem: C = US...
error 2 at 1 depth lookup:unable to get issuer certificate
Plus précisément, le incapable d'obtenir le certificat d'émetteur .
Obtenez-le également ici:
$ openssl verify chain.pem
chain.pem: C = US...
error 20 at 0 depth lookup:unable to get local issuer certificate
$ openssl verify cert.pem
cert.pem: C...
error 20 at 0 depth lookup:unable to get local issuer certificate
Enfin, je l'obtiens dans Node.js lorsque je passe les clés à un serveur HTTPS:
events.js:193
throw er; // Unhandled 'error' event
^
Error: unable to get local issuer certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at emitNone (events.js:115:13)
at TLSSocket.emit (events.js:218:7)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
J'ai essayé de le passer avec { key, cert, ca }
, mais toujours la même erreur.
Vous vous demandez comment procéder pour déboguer cela ou quel est le correctif pour faire fonctionner un serveur HTTPS.
Si j'utilise un fichier pfx
, j'obtiens ce qui suit:
events.js:193
throw er; // Unhandled 'error' event
^
Error: self signed certificate in certificate chain
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at emitNone (events.js:115:13)
at TLSSocket.emit (events.js:218:7)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
Si je ne laisse que le cert.pem dans le fichier cert, et que l'attribut ca
soit ca-cert.pem, cela donne:
Error: unable to verify the first certificate
at TLSSocket.<anonymous> (_tls_wrap.js:1108:38)
at emitNone (events.js:105:13)
at TLSSocket.emit (events.js:207:7)
at TLSSocket._finishInit (_tls_wrap.js:638:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:468:38)
Je ne sais pas quoi faire.
Ici ils disent:
OpenSSL n'est pas en mesure de trouver un certificat local pour l'émetteur (ou l'émetteur du premier certificat de la chaîne reçu du serveur Web lors de la négociation TLS) avec lequel vérifier la ou les signatures.
Je ne suis pas sûr de ce que cela veut dire.
Cette erreur signifie que le chemin ou la chaîne de certificat est rompu et qu'il vous manque des fichiers de certificat.
- https://wiki.zimbra.com/wiki/Fix_depth_lookup:unable_to_get_issuer_certificate
Mise à jour
Un peu plus d'aide:
Ce problème est généralement indiqué par des messages de journal indiquant quelque chose comme "impossible d'obtenir le certificat d'émetteur local" ou "certificat auto-signé". Lorsqu'un certificat est vérifié, son autorité de certification racine doit être "approuvée" par OpenSSL, cela signifie généralement que le certificat de l'autorité de certification doit être placé dans un répertoire ou un fichier et que le programme approprié doit être configuré pour le lire. Le programme OpenSSL 'verify' se comporte de manière similaire et émet des messages d'erreur similaires: consultez la page de manuel du programme verify (1) pour plus d'informations.
Mais ça n'aide pas beaucoup.
On dirait que Node.js utilise un 1.0.2l au lieu de 1.0.2m mais ne semble pas être un gros problème.
$ node -pe process.versions | grep openssl
openssl: '1.0.2l'
Mise à jour 2
Bizarre, j'obtiens ceci quand je fais une demande de Node.js:
Uncaught Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
Mais lorsque je vais dans le navigateur, je ne vois pas la page "Procéder avec prudence" et je peux enregistrer une demande avec succès dans Node.js. Peut-être que cela aide quelque peu. Veuillez aider: D
(Cette réponse extraite de X509_verify_cert
à crypto/x509/x509_vfy.c:204
, dans openssl-1.0.2m)
L'application OpenSSL verify
vérifie un certificat de la manière suivante: elle crée la chaîne de certificats en commençant par le certificat cible et en traçant la chaîne émettrice, en recherchant d'abord tous les certificats non approuvés fournis avec le certificat cible. En cas d'échec à trouver un certificat d'émetteur non approuvé, OpenSSL bascule vers le magasin de certificats approuvé et continue de créer la chaîne. Ce processus s'arrête lorsque
- un émetteur est introuvable dans le magasin approuvé.
- un certificat auto-signé est rencontré.
- la profondeur de vérification maximale est rencontrée.
À ce stade, nous avons une chaîne qui peut se terminer prématurément (si nous n'avons pas trouvé d'émetteur ou si nous avons dépassé la profondeur de vérification).
OpenSSL analyse ensuite chaque certificat approuvé de la chaîne à la recherche d'extensions SSLv3 qui spécifient le but du certificat approuvé. Si le certificat approuvé a les bons attributs "d'approbation" pour le "but" de l'opération de vérification (ou a l'attribut anyExtendedKeyUsage
), la chaîne est approuvée. (Pardonnez la vague sur les attributs de confiance, cette partie du code était difficile à lire.)
Permet donc de le tester. Reprenons d'abord les cas d'erreur de l'OP:
#
echo "Making Root CA..."
openssl req -newkey rsa:4096 -nodes -keyout ca-key.pem -sha384 -x509 -days 365 -out ca-crt.pem -subj /C=XX/ST=YY/O=RootCA
echo "Making Intermediate CA..."
openssl req -newkey rsa:3072 -nodes -keyout int-key.pem -new -sha384 -out int-csr.pem -subj /C=XX/ST=YY/O=IntermediateCA
openssl x509 -req -days 360 -in int-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out int-crt.pem
echo "Making User Cert..."
openssl req -newkey rsa:2048 -nodes -keyout usr-key.pem -new -sha256 -out usr-csr.pem -subj /C=XX/ST=YY/O=LockCmpXchg8b
openssl x509 -req -days 360 -in usr-csr.pem -CA int-crt.pem -CAkey int-key.pem -CAcreateserial -out usr-crt.pem
echo ""
echo "Making Chain..."
cat ca-crt.pem int-crt.pem > chain.pem
echo ""
echo "Verfying UserCert via RootCA..."
openssl verify -CAfile ca-crt.pem usr-crt.pem
echo ""
echo "Verfying UserCert via IntermediateCA..."
openssl verify -CAfile int-crt.pem usr-crt.pem
echo ""
echo "Verfying UserCert via chain..."
openssl verify -CAfile chain.pem usr-crt.pem
les rendements
[... Skipping OpenSSL KeyGen / CertGen verbosity ...]
Making Chain...
Verfying UserCert via RootCA...
usr-crt.pem: C = XX, ST = YY, O = LockCmpXchg8b
error 20 at 0 depth lookup:unable to get local issuer certificate
Verfying UserCert via IntermediateCA...
usr-crt.pem: C = XX, ST = YY, O = IntermediateCA
error 2 at 1 depth lookup:unable to get issuer certificate
Verfying UserCert via chain...
usr-crt.pem: OK
Maintenant, utilisons le -addtrust
option de openssl x509
pour vous assurer que nous avons l'un des attributs de confiance acceptables sur l'autorité de certification intermédiaire (appelez celui-ci IntermediateCAWithTrust
; nous l'utiliserons pour signer AnotherUserCert
.):
echo ""
echo "Alternate Intermedate CA (using -addtrust anyExtendedKeyUsage)"
echo ""
echo "Making IntermediateCAWithTrust..."
openssl req -newkey rsa:3072 -nodes -keyout int-key2.pem -new -sha384 -out int-csr2.pem -subj /C=XX/ST=YY/O=IntermediateCAWithTrust
openssl x509 -req -days 360 -in int-csr2.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out int-crt2.pem -addtrust anyExtendedKeyUsage
echo "Making AnotherUser Cert..."
openssl req -newkey rsa:2048 -nodes -keyout usr-key2.pem -new -sha256 -out usr-csr2.pem -subj /C=XX/ST=YY/O=LockCmpXchg8b_2
openssl x509 -req -days 360 -in usr-csr2.pem -CA int-crt2.pem -CAkey int-key2.pem -CAcreateserial -out usr-crt2.pem
echo ""
echo "Verfying AnotherUserCert via IntermediateCAWithTrust..."
openssl verify -CAfile int-crt2.pem usr-crt2.pem
Cela donne
Alternate Intermedate CA (using -addtrust anyExtendedKeyUsage)
Making IntermediateCAWithTrust...
[... Snip more OpenSSL generation output ...]
Making AnotherUser Cert...
[... Snip more OpenSSL generation output ...]
Verfying AnotherUserCert via IntermediateCAWithTrust...
usr-crt2.pem: OK
Hé regarde! nous venons de vérifier avec succès AnotherUserCert via IntermediateCAWithTrust, même si nous n'avons pas fourni toute la chaîne. La clé de cette différence est que l'un des certificats approuvés de la chaîne avait un attribut d'approbation approprié pour l'opération de vérification.
En regardant de plus près (via openssl x509 -in ca-crt.pem -noout -text
), notre certificat CA a
X509v3 Basic Constraints:
CA:TRUE
que j'imagine qu'OpenSSL traite comme une extension générale "peut vérifier pour n'importe quel but". Le nouveau IntermediateCAWithTrust
n'a pas X509v3 Basic Constraints
, mais à la place
Trusted Uses:
Any Extended Key Usage
No Rejected Uses.
Pour plus d'informations dans le -addtrust
option, et les types d'attributs de confiance qui peuvent être ajoutés, voir https://www.openssl.org/docs/manmaster/man1/x509.html#TRUST_SETTINGS
Au bas de cette page se trouve un résumé concis de la discussion précédente:
L'indicateur CA de l'extension basicConstraints est utilisé pour déterminer si le certificat peut être utilisé en tant qu'autorité de certification. Si le drapeau CA est vrai, alors c'est un CA, si le drapeau CA est faux alors ce n'est pas un CA. Toutes les autorités de certification doivent avoir le drapeau CA défini sur true.
Si l'extension basicConstraints est absente, le certificat est considéré comme une "CA possible". Les autres extensions sont vérifiées en fonction de l'utilisation prévue du certificat. Un avertissement est donné dans ce cas car le certificat ne doit vraiment pas être considéré comme une autorité de certification: cependant, il est autorisé d'être une autorité de certification pour contourner certains logiciels défectueux.
Donc, en bref, assurez-vous que vos autorités de certification intermédiaires sont correctement des autorités de certification (dans leur X509v3 Basic Constraints
). Cela semble un excellent tutoriel (et il génère explicitement l'AC intermédiaire en tant qu'AC): https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html
En tant que plan de sauvegarde, vous pouvez toujours fournir toute la chaîne, ou vous pouvez créer vos autorités de certification intermédiaires avec le -addtrust
pirater.
https://letsencrypt.org/ est vraiment facile à utiliser et gratuit. Exécutez également le nœud sans SSL sur un port HTTP local et utilisez NGINX comme proxy HTTPS.
Sudo apt-get install certbot nginx
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$Host$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl on;
ssl_certificate /etc/letsencrypt/live/Host.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/Host.com/privkey.pem;
access_log /var/log/nginx/Host.access.log;
error_log /var/log/nginx/Host.error.log;
server_name _;
gzip on;
gzip_proxied any;
gzip_types text/css text/javascript text/xml text/plain application/javascript application/x-javascript application/json;
location / {
include /etc/nginx/proxy_params;
proxy_pass http://localhost:8080;
proxy_read_timeout 90s;
proxy_redirect http://localhost:8080 https://www.Host.com;
}
}