OpenSSL 验证返回代码: 20(无法获得本地颁发者证书)

我正在运行 Windows Vista,并试图通过 https 连接上传一个多部分形式的文件,但我有一些麻烦与本地发行证书。我只是想弄清楚为什么现在这个不工作,并在稍后回到我的 cURL 代码解决了这个问题。我运行命令:

openssl s_client -connect connect_to_site.com:443

它给了我一个来自 VeriSign 公司的数字证书,但也发出了一个错误:

Verify return code: 20 (unable to get local issuer certificate)

什么是本地发行证书?这是我电脑里的证明吗?有办法解决吗?我已经尝试使用-CAfile mozilla.pem 文件,但仍然给我相同的错误。

255111 次浏览

Is your server configured for client authentication? If so you need to pass the client certificate while connecting with the server.

I had the same problem and solved it by passing path to a directory where CA keys are stored. On Ubuntu it was:

openssl s_client -CApath /etc/ssl/certs/ -connect address.com:443

I had the same problem on OSX OpenSSL 1.0.1i from Macports, and also had to specify CApath as a workaround (and as mentioned in the Ubuntu bug report, even an invalid CApath will make openssl look in the default directory). Interestingly, connecting to the same server using PHP's openssl functions (as used in PHPMailer 5) worked fine.

With client authentication:

openssl s_client -cert ./client-cert.pem -key ./client-key.key -CApath /etc/ssl/certs/ -connect foo.example.com:443

This error also happens if you're using a self-signed certificate with a keyUsage missing the value keyCertSign.

Solution: You must explicitly add the parameter -CAfile your-ca-file.pem.

Note: I tried also param -CApath mentioned in another answers, but is does not works for me.

Explanation: Error unable to get local issuer certificate means, that the openssl does not know your root CA cert.


Note: If you have web server with more domains, do not forget to add also -servername your.domain.net parameter. This parameter will "Set TLS extension servername in ClientHello". Without this parameter, the response will always contain the default SSL cert (not certificate, that match to your domain).

I faced the same issue, It got fixed after keeping issuer subject value in the certificate as it is as subject of issuer certificate.

so please check "issuer subject value in the certificate(cert.pem) == subject of issuer (CA.pem)"

openssl verify -CAfile CA.pem cert.pem
cert.pem: OK

put your CA & root certificate in /usr/share/ca-certificate or /usr/local/share/ca-certificate. Then

dpkg-reconfigure ca-certificates

or even reinstall ca-certificate package with apt-get.

After doing this your certificate is collected into system's DB: /etc/ssl/certs/ca-certificates.crt

Then everything should be fine.

Create the certificate chain file with the intermediate and root ca.

cat intermediate/certs/intermediate.cert.pem certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem


chmod 444 intermediate/certs/ca-chain.cert.pem

Then verfify

openssl verify -CAfile intermediate/certs/ca-chain.cert.pem \
intermediate/certs/www.example.com.cert.pem

www.example.com.cert.pem: OK Deploy the certific

this error messages means that CABundle is not given by (-CAfile ...) OR the CABundle file is not closed by a self-signed root certificate.

Don't worry. The connection to server will work even you get theis message from openssl s_client ... (assumed you dont take other mistake too)

I would update @user1462586 answer by doing the following:

I think it is more suitable to use update-ca-certificates command, included in the ca-certificates package than dpkg-reconfigure.

So basically, I would change its useful answer to this:

  1. Retrieve the certificate (from this stackoverflow answer and write it in the right directory:
# let's say we call it my-own-cert.crt
openssl s_client -CApath /etc/ssl/certs/ -connect <hostname.domain.tld>:<port> 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /usr/share/ca-certificates/my-own-cert.crt

Repeat the operation if you need other certificates.

For example, if you need CA certs for ldaps/starttls with Active Directory, see here for how to process this + use openssl to convert it in pem/crt:

openssl x509 -inform der -in LdapSecure.cer -out my-own-ca.pem
#and copy it in the right directory...
cp my-own-ca.pem /usr/share/ca-certificates/my-own-ca.crt
  1. Add this certificates to the /etc/ca-certificates.conf configuration file:
echo "my-own-cert.crt" >> /etc/ca-certificates.conf
echo "my-own-ca.crt" >> /etc/ca-certificates.conf
  1. Update /etc/ssl/certs directory:
update-ca-certificate
  1. Enjoy

Note that if you use private domain name machines, instead of legitimate public domain names, you may need to edit your /etc/hosts file to be able to have the corresponding FQDN.

I got this problem when my NGINX server did not have a complete certificate chain in the certificate file it was configured with.

My solution was to find a similar server and extract the certificates from that server with something like:

openssl s_client -showcerts -CAfile my_local_issuer_CA.cer -connect my.example.com:443 > output.txt

Then I added the ASCII armoured certificates from that 'output.txt' file (except the machine-certificate) to a copy of my machines certificate-file and pointed NGINX at that copied file instead and the error went away.

This is due to SNI Certificate binding issue on the Vserver or server itself