Message d’erreur
verify error:num=20:unable to get local issuer certificate
Également affiché sous la forme
- Verify return code: 20 (unable to get local issuer certificate)
- error 20 at 0 depth lookup: unable to get local issuer certificate
s_client affiche « verify error:num=20:… » pendant le handshake et « Verify return code: 20 (…) » dans son récapitulatif ; openssl verify affiche « error 20 at <depth> depth lookup: … ». Par défaut, s_client continue après les erreurs de vérification ; ajoutez -verify_return_error pour qu’il échoue.
OpenSSL CLI (openssl s_client / openssl verify) — X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
Ce que cela signifie
Erreur OpenSSL 20 (X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) : en construisant la chaîne, OpenSSL est arrivé à un certificat dont il n’a pas trouvé l’émetteur, ni parmi les certificats envoyés par le serveur, ni dans le magasin de confiance. La ligne depth affichée juste avant désigne le certificat dont l’émetteur manque. C’est ce même code qui se cache derrière le (60) de curl, le CERTIFICATE_VERIFY_FAILED de Python et le UNABLE_TO_GET_ISSUER_CERT_LOCALLY de Node.js.
Pourquoi cela se produit
La chaîne se termine par une racine absente du magasin
fréquenteUne racine privée ou d’entreprise (ou un proxy d’inspection TLS qui n’envoie que son certificat intermédiaire). La ligne depth la plus élevée désigne un certificat intermédiaire dont vous n’avez pas l’émetteur.
Le serveur n’envoie pas son certificat intermédiaire
fréquenteSeul depth=0 apparaît, et son émetteur est une AC intermédiaire. OpenSSL ne télécharge jamais les certificats intermédiaires manquants : le serveur doit donc les envoyer.
Aucun magasin de confiance n’a été utilisé pour le test
occasionnelleopenssl verify avec un certificat isolé, ou s_client dans une image sans ca-certificates, n’a aucune racine pour terminer la chaîne, même pour des sites publics.
Comment corriger l’erreur
- 1.
Lire les lignes depth
La profondeur 0 correspond au certificat du serveur, les numéros supérieurs aux certificats intermédiaires qu’il a envoyés. La dernière ligne depth avant l’erreur désigne le certificat dont l’émetteur manque.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>&1 | grep -E '^depth|verify' # depth=1 CN=Example Corp Issuing CA <- the highest certificate received # verify error:num=20:... <- its issuer is not in the trust store - 2.
Tester avec la racine attendue
-CAfile avec la bonne racine (et -verify_return_error pour rendre les échecs fatals) montre si cette racine complète la chaîne ; « Verify return code: 0 (ok) » signifie que c’est le cas.
bash # Verify against a specific root (exit code and "Verify return code: 0 (ok)" confirm it) echo | openssl s_client -connect api.example.com:443 -servername api.example.com \ -CAfile corp-root-ca.pem -verify_return_error 2>&1 | grep 'Verify return code' - 3.
Vérifier les fichiers de certificats hors ligne
Fournissez à openssl verify la racine via -CAfile et les certificats intermédiaires via -untrusted ; un certificat feuille seul ne peut pas être vérifié.
bash # Offline: root as trust anchor, intermediate(s) as untrusted helpers openssl verify -CAfile corp-root-ca.pem -untrusted intermediate.pem server.pem - 4.
Installer la racine dans le magasin du système
Lorsque la chaîne se termine légitimement par une racine d’entreprise, ajoutez-la au magasin de la distribution ; les outils de la machine reposant sur OpenSSL l’approuvent alors.
bash sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt sudo update-ca-certificates # openssl reads /etc/ssl/certs by default on Debian/Ubuntu
Erreurs associées
verify error:num=21:unable to verify the first certificateOpenSSL CLI (openssl s_client)verify error:num=19:self-signed certificate in certificate chainOpenSSL CLI (openssl s_client / openssl verify)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local…Python ssl module (OpenSSL)