/errors/openssl/unable-to-get-local-issuer-certificate
unable to get local issuer certificate (OpenSSL verify error 20)
- tool
- OpenSSL
- exit code
- 2
- versions
- OpenSSL 1.1.1, OpenSSL 3.x, OpenSSL 4.0
- os
- linux, macos, windows
unable to get local issuer certificate (X509 verify error 20) means OpenSSL found the certificate but not the certificate of the CA that signed it, neither in the chain it received nor in the local trust store. Provide the missing CA or intermediate certificate.
Reproduce the error
A leaf certificate signed by a private CA, verified without telling OpenSSL about that CA:
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout ca.key -out ca.pem -subj "/CN=Example Root CA" -days 30 2>/dev/null
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout leaf.key -out leaf.csr -subj "/CN=app.example.test" 2>/dev/null
openssl x509 -req -in leaf.csr -CA ca.pem -CAkey ca.key -out leaf.pem -days 10 2>/dev/null
openssl verify leaf.pemOutput · exit 2
CN=app.example.test error 20 at 0 depth lookup: unable to get local issuer certificate error leaf.pem: verification failed
Fix: provide the issuer
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout ca.key -out ca.pem -subj "/CN=Example Root CA" -days 30 2>/dev/null
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout leaf.key -out leaf.csr -subj "/CN=app.example.test" 2>/dev/null
openssl x509 -req -in leaf.csr -CA ca.pem -CAkey ca.key -out leaf.pem -days 10 2>/dev/null
openssl verify -CAfile ca.pem leaf.pemOutput
leaf.pem: OK
The same idea applies to every client: curl --cacert ca.pem, Python requests.get(url, verify="ca.pem"), Node.js NODE_EXTRA_CA_CERTS=ca.pem.
When the server is at fault
If public clients fail too, the server probably omits its intermediate certificate. Check what it sends:
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/nullA correct server sends the leaf and every intermediate up to (not including) the root. With Let's Encrypt and nginx, point ssl_certificate at fullchain.pem, not cert.pem.