我正在尝试下载证书链并在本地验证它,因为新的 CA 证书被推送给客户端,基本上可以了解哪些网站在任何给定时间都可以工作。我使用以下命令来下载链:
echo -n | openssl s_client -showcerts -connect example.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > mycert.pem
但是在使用时openssl verify
我收到错误消息:
root@host:~# openssl version
OpenSSL 1.1.0e 16 Feb 2017
root@host:~# echo -n | openssl s_client -showcerts -connect example.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > mycert.pem
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
verify return:1
depth=0 C = US, ST = California, L = Los Angeles, O = Internet Corporation for Assigned Names and Numbers, OU = Technology, CN = www.example.org
verify return:1
DONE
root@host:~# openssl verify mycert.pem
C = US, ST = California, L = Los Angeles, O = Internet Corporation for Assigned Names and Numbers, OU = Technology, CN = www.example.org
error 20 at 0 depth lookup: unable to get local issuer certificate
error mycert.pem: verification failed
离线验证这样的证书链的正确方法是什么?
答案1
您应该将要验证的证书放在一个文件中,并将链放在另一个文件中:
openssl verify -CAfile chain.pem mycert.pem
当然,了解openssl
如何查找根证书(如果未包含在 chain.pem 中)也很重要。如果您需要执行此操作(如果您使用自己的 CA),那么您也可以指定一个替代目录来查找它-CApath
答案2
所以我找到了答案,OpenSSL 仅验证文件中的第一个证书。这意味着如果您有有效的链,您应该只验证最后一个证书。
答案3
certtool
您可以通过和 的组合来实现您想要的结果openssl
。值得注意的是,这里涉及两件事,一是验证链本身,二是检查该链是否受到本地安装的受信任根证书的信任。
警告:检查负面案例
请检查负面案例,即确保您的测试应将应视为无效的内容正确地视为无效。你可以这样做https://badssl.com/或者你自己做的东西。如果您不确定无论您正在测试什么,负面案例都会失败,那么测试将不会有太大帮助。
验证链是否可信:
openssl s_client -showcerts -connect example.com:443 </dev/null 2>/dev/null \
| sed -ne '/-BEGIN/,/-END/p' \
| certtool --verify
仅验证链的一致性 - 但不验证信任:
openssl s_client -showcerts -connect example.com:443 </dev/null 2>/dev/null \
| sed -ne '/-BEGIN/,/-END/p' \
| certtool --verify-chain
可信链示例:
$ openssl s_client -showcerts -connect example.com:443 </dev/null 2>/dev/null | sed -ne '/-BEGIN/,/-END/p' | certtool --verify
Loaded system trust (154 CAs available)
Subject: CN=DigiCert SHA2 Secure Server CA,O=DigiCert Inc,C=US
Issuer: CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
Signature algorithm: RSA-SHA256
Output: Not verified. The certificate is NOT trusted. The certificate issuer is unknown.
Subject: CN=DigiCert SHA2 Secure Server CA,O=DigiCert Inc,C=US
Issuer: CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
Signature algorithm: RSA-SHA256
Output: Not verified. The certificate is NOT trusted. The certificate issuer is unknown.
Subject: CN=DigiCert SHA2 Secure Server CA,O=DigiCert Inc,C=US
Issuer: CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
Checked against: CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
Signature algorithm: RSA-SHA256
Output: Verified. The certificate is trusted.
Subject: CN=www.example.org,OU=Technology,O=Internet Corporation for Assigned Names and Numbers,L=Los Angeles,ST=California,C=US
Issuer: CN=DigiCert SHA2 Secure Server CA,O=DigiCert Inc,C=US
Checked against: CN=DigiCert SHA2 Secure Server CA,O=DigiCert Inc,C=US
Signature algorithm: RSA-SHA256
Output: Verified. The certificate is trusted.
Chain verification output: Verified. The certificate is trusted.
不可信链的示例:
$ openssl s_client -showcerts -connect untrusted-root.badssl.com:443 </dev/null 2>/dev/null | sed -ne '/-BEGIN/,/-END/p' | certtool --verify
Loaded system trust (154 CAs available)
Subject: CN=*.badssl.com,O=BadSSL,L=San Francisco,ST=California,C=US
Issuer: CN=BadSSL Untrusted Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US
Signature algorithm: RSA-SHA256
Output: Not verified. The certificate is NOT trusted. The certificate issuer is unknown.
Subject: CN=*.badssl.com,O=BadSSL,L=San Francisco,ST=California,C=US
Issuer: CN=BadSSL Untrusted Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US
Signature algorithm: RSA-SHA256
Output: Not verified. The certificate is NOT trusted. The certificate issuer is unknown.
Subject: CN=*.badssl.com,O=BadSSL,L=San Francisco,ST=California,C=US
Issuer: CN=BadSSL Untrusted Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US
Signature algorithm: RSA-SHA256
Output: Not verified. The certificate is NOT trusted. The certificate issuer is unknown.
Chain verification output: Not verified. The certificate is NOT trusted. The certificate issuer is unknown.
检查不受信任的链是否有效:
$ openssl s_client -showcerts -connect untrusted-root.badssl.com:443 </dev/null 2>/dev/null | sed -ne '/-BEGIN/,/-END/p' | certtool --verify-chain
Subject: CN=*.badssl.com,O=BadSSL,L=San Francisco,ST=California,C=US
Issuer: CN=BadSSL Untrusted Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US
Checked against: CN=BadSSL Untrusted Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US
Signature algorithm: RSA-SHA256
Output: Verified. The certificate is trusted.
Chain verification output: Verified. The certificate is trusted.
答案4
问题出在-showcerts
命令的输出中:您只有您的证书和签名它的证书 - 并且可能是中间证书,但不是完整的链。要获得 OK 语句,您应该:
- 将您的证书(第一个
-BEGIN END-
块)放入文件中mycert.crt
- 将其他的放入文件中
CAcerts.crt
- 检查以
openssh -text -in CAcerts.crt
查找对此进行签名的根 CA,并将其添加到CAfile.crt
. - 如果 CA 仍然不是根 CA(自签名),则可以重复此操作。
- 然后验证您的证书:
openssl verify -CAfile CAcerts.crt mycert.crt
注意:您可以使用首选项 GUI(查看证书然后导出)或在命令行中使用certutil
Firefox 配置文件目录中的 来从 Firefox 商店获取众所周知的 CA 证书。例如:
$ find $HOME/.mozilla/firefox -name cert8.db # point for example to abcdef.default directory
$ certutil -a -L -d $HOME/.mozilla/firefox/abcdef.default/ -n "Let's Encrypt` Authority X3"