我有一个简单的链设置,在这种情况下可以成功验证:
$ 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 }
传递,但仍然相同的错误。
想知道如何调试此问题或要运行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,然后将 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无法找到发行人的本地证书(或在TLS握手期间从Web服务器接收的链中的第一个证书的发行人)可以验证签名(S)。
不确定这是什么意思。
此错误意味着证书路径或链条被打破,您缺少证书文件。
- https://wiki.zimbra.com/wiki/fix_depth_lookup:unable_to_to_get_issuer_certificate
update
更多的帮助:
通常由日志消息表明此问题,说"无法获得本地发行人证书"或"自签名证书"之类的东西。验证证书后,必须由OpenSL"信任"其根CA,这通常意味着必须将CA证书放置在目录或文件中,并配置为读取它的相关程序。OPENSL程序"验证"以类似的方式行为,并发出相似的错误消息:检查验证(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中成功记录请求。也许有些有帮助。请帮助:D
(此答案从 X509_verify_cert
at crypto/x509/x509_vfy.c:204
中提取,在openssl-1.0.2m中)
OPENSL verify
应用程序以以下方式验证证书:它以目标证书开头建立证书链,并追踪发行人链,搜索首先与目标证书一起提供的任何不信任证书。在未能找到不受信任的发行人证书后,OpenSSL会切换到受信任的证书商店,并继续建造链条。此过程停止
- 在受信任的商店中找不到发行人。
- 遇到一个自签名的证书。
- 遇到最大验证深度。
在这一点上,我们有一条可能过早结束的链(如果我们找不到发行人,或者如果超过了验证深度)。
openssl然后扫描链条上的每个受信任证书,以寻找指定可信证书目的的SSLV3扩展名。如果信任的证书具有正确的"信任"属性,以实现验证操作的"目的"(或具有anyExtendedKeyUsage
属性),则链被信任。(请原谅信任属性的手波,很难阅读代码的一部分。)
所以让我们进行测试。首先,让我们重复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成功验证了另一个usercert。这种差异的关键是,链中的任何一个受信任的证书都具有适当的信任属性用于验证操作。
看近一点(via openssl x509 -in ca-crt.pem -noout -text
),我们的CA证书具有
X509v3 Basic Constraints:
CA:TRUE
我可以想象,Openssl将其视为一般的"可能出于任何目的验证"扩展。新的IntermediateCAWithTrust
没有X509v3 Basic Constraints
,而是具有
Trusted Uses:
Any Extended Key Usage
No Rejected Uses.
有关-addtrust
选项中的更多信息以及可以添加的信任属性类型,请访问https://www.openssl.org/docs/manmaster/manmaster/man1/man1/x509.html#trustrongettings
该页面底部附近是上述讨论的简明摘要:
basic -constraints扩展CA标志用于确定是否是否 该证书可用作CA。如果CA标志为真,那是 CA,如果CA标志为false,则不是CA。所有CAS都应该有 CA标志设置为true。
如果不存在基本限制扩展,则证书为 被认为是检查其他扩展的"可能的CA" 根据预期的证书使用。发出警告 在这种情况下,因为证书实际上不应被视为 CA:但是,它可以成为CA,可以解决一些破裂 软件。
因此,简而言之,请确保您的中间CAS正确(在X509v3 Basic Constraints
中)。这似乎是一个很棒的教程(并且明确生成了中间的CA):https://jamielinux.com/docs/openssl-certificate-authority/create-the-the-the-the-the-the-the-the-the-root-pair.html
作为备份计划,您始终可以提供整个链条,也可以使用-addtrust
黑客制作中级CAS。
https://letsencrypt.org/真的很容易使用和免费。另外,在本地HTTP端口上运行没有SSL的节点,并将NGINX用作HTTPS代理。
sudo apt-get安装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;
}
}