OpenSSL错误 – 无法获得本地颁发者证书

我有一个简单的链设置,可以成功validation在这种情况下:

$ openssl version OpenSSL 1.0.2m 2 Nov 2017 $ openssl verify -CAfile chain.pem cert.pem cert.pem: OK 

但是,我在这些情况下得到错误:

 $ openssl verify -CAfile ca-cert.pem cert.pem cert.pem: C = US... error 2 at 1 depth lookup:unable to get issuer certificate 

特别是无法获得发行人证书

另请参阅:

 $ 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 

最后,当我将密钥传递给HTTPS服务器时,我在Node.js中获取它:

 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) 

我试着用{ key, cert, ca }传递它,但仍然是一样的错误。

想知道如何去debugging这个问题或者修复什么来获得一个HTTPS服务器的运行。

如果我使用一个pfx文件,我得到以下内容:

 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) 

如果我只将cert.pem保留在cert文件中,并使ca属性成为ca-cert.pem,则它将:

 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) 

不知道该怎么办。

他们在这里说:

OpenSSL无法为validation签名的发行者(或在TLS握手期间从Web服务器收到的链中第一个证书的颁发者)find本地证书。

不确定那是什么意思。

此错误意味着证书path或连锁断开,您缺less证书文件。

– https://wiki.zimbra.com/wiki/Fix_depth_lookup:unable_to_get_issuer_certificate

更新

稍微有点帮助:

这个问题通常由日志消息表示,如“无法获得本地签发人证书”或“自签名证书”。 当证书被validation时,它的根CA必须被OpenSSL“信任”,这通常意味着CA证书必须被放置在一个目录或文件中,并且相关程序被configuration为读取它。 OpenSSL程序“validation”的行为类似,并发出类似的错误消息:检查verify(1)程序手册页以获取更多信息。

  • https://www.openssl.org/docs/faq.html#USER6

但是还是没有太大的帮助。

看起来像Node.js使用1.0.2l而不是1.0.2m,但似乎不是一个大问题。

 $ node -pe process.versions | grep openssl openssl: '1.0.2l' 

更新2

奇怪的是,当我从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) 

但是当我去浏览器,我没有看到“继续谨慎”页面,并可以成功地在Node.js中logging一个请求。 也许这有些帮助。 请帮助:D

(这个答案从crypto/x509/x509_vfy.c:204中的X509_verify_cert中提取,在openssl-1.0.2m中)

OpenSSL verify应用程序按以下方式validation证书:从目标证书开始构build证书链,并跟踪发行者链,首先search与目标证书一起提供的任何不可信证书。 在找不到不可信任的颁发者证书时,OpenSSL切换到受信任的证书库并继续构build链。 此过程停止时

  1. 在可信商店中找不到发行人。
  2. 遇到自签名证书。
  3. 遇到最大validation深度。

在这一点上,我们有一个可能过早结束的链条(如果我们没有find发行者,或者我们超过了validation深度)。

然后,OpenSSL扫描链上的每个可信证书,查找指定可信证书用途的SSLv3扩展。 如果可信证书具有用于validation操作的“目的”(或具有anyExtendedKeyUsage属性)的权利“信任”属性,则该信任链是可信的。 (原谅信任属性的手势,这部分代码很难阅读。)

所以让我们testing一下。 首先,让我们重新看看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 

产量

 [... 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 

现在,让我们使用openssl x509-addtrust选项来确保在中间CA上有一个可接受的信任属性(称为IntermediateCAWithTrust ;我们将使用它来签署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 

这收益率

 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 

你看! 我们通过IntermediateCAWithTrust成功validationAnotherUserCert,即使我们没有提供整个链。 这种差异的关键在于中的任何一个可信证书都具有用于validation操作的适当的信任属性

再仔细看看( via openssl x509 -in ca-crt.pem -noout -text ),我们的CA证书有

  X509v3 Basic Constraints: CA:TRUE 

我可以想象OpenSSL被视为一般的“可以为任何目的validation”扩展。 新的IntermediateCAWithTrust没有X509v3 Basic Constraints ,但是却有

 Trusted Uses: Any Extended Key Usage No Rejected Uses. 

有关-addtrust选项的更多信息以及可添加的信任属性的types,请参阅https://www.openssl.org/docs/manmaster/man1/x509.html#TRUST_SETTINGS

在该页面的底部附近是前面讨论的简要概述:

basicConstraints扩展CA标志用于确定证书是否可以用作CA. 如果CA标志为真,那么它是CA,如果CA标志是假的,则它不是CA. 所有CA应该将CA标志设置为true。

如果basicConstraints扩展缺失,则证书被认为是“可能的CA”,根据证书的预期用途检查其他扩展。 在这种情况下会给出一个警告,因为证书实际上不应该被视为一个CA:但是允许它成为CA来解决一些破碎的软件。

所以,简而言之,确保您的中间CA是正确的CA(在他们的X509v3 Basic Constraints )。 这似乎是一个很好的教程(它明确生成中间CA作为CA): https : //jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html

作为备份计划,您可以随时提供整个链,或者您可以使用-addtrust hack来制作中间CA。

https://letsencrypt.org/是非常容易使用和免费的&#x3002; 另外,在本地HTTP端口上运行没有SSL的节点,并使用NGINX作为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; } }