use*_*637 8 verification openssl certificate
有一个自签名的根CA证书rootcert.pem,具有以下V3扩展:
X509v3 extensions:
X509v3 Key Usage:
Certificate Sign
X509v3 Basic Constraints:
CA:TRUE
Run Code Online (Sandbox Code Playgroud)
rootcert.pem将CA标志设置为true,其密钥用法允许证书签名.rootcert.pem使用以下V3扩展名签署证书foocert.pem:
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment
Run Code Online (Sandbox Code Playgroud)
foocert.pem将CA标志设置为false,其密钥用法不允许证书签名.但是,让我们说,foocert.pem签署了一个rougecert.pem.
形成foocert&roguecert的证书链:
cat foocert.pem roguecert.pem > roguechain.pem
Run Code Online (Sandbox Code Playgroud)
使用openssl验证进行验证.验证成功:
$ openssl verify -CAfile rootcert.pem roguechain.pem
roguechain.pem: OK
Run Code Online (Sandbox Code Playgroud)
使用x509_strict验证,仍然成功:
$ openssl verify -x509_strict -CAfile rootcert.pem badchain.pem
badchain.pem: OK
Run Code Online (Sandbox Code Playgroud)
假设系统只信任根CA证书.对等体提供其证书链,其中一个中间证书不应该是CA(CA设置为false并且密钥用法不允许证书签名),仍然openssl标记链是好的吗?
我如何让openssl不信任这样的链?
原来的答案证明是错的,所以这是另一个:)
看起来openssl验证只进行证书链验证,并且它不检查任何标志(即使使用正确的设置).但是,当您实际执行ssl/tls连接时,库会检查标志:
$ openssl s_client -verify 100 -CAfile cacert.pem -connect servername:443
verify depth is 100
CONNECTED(00000003)
depth=1 /CN=middle
verify error:num=24:invalid CA certificate
verify return:1
depth=1 /CN=middle
verify error:num=26:unsupported certificate purpose
verify return:1
depth=2 /CN=root
verify return:1
depth=1 /CN=middle
verify return:1
depth=0 /CN=leaf
verify return:1
---
Certificate chain
0 s:/CN=leaf
i:/CN=middle
1 s:/CN=middle
i:/CN=root
---
...
SSL-Session:
Protocol : TLSv1
...
Verify return code: 26 (unsupported certificate purpose)
Run Code Online (Sandbox Code Playgroud)
(编辑:刚刚注意到我的答案是 Chris Lesner 的更长更详细的版本,我会投票给他,但我还没有这里的代表:>)
我认为你在这里仍然在错误的轨道上。我认为实际问题是“验证”不会以这种方式验证单个文件中的链。
'verify' 的最后一个参数被列为[certificates]并记录如下:
certificates
One or more certificates to verify. If no certificates are given, verify will attempt to read a
certificate from standard input. Certificates must be in PEM format.
Run Code Online (Sandbox Code Playgroud)
您可以传递多个文件 - 但每个文件都将作为单个叶证书进行验证,独立于其他文件。这不是绝对明确的,但它暗示(我可以告诉您事实确实如此;有关详细信息,请参阅下面的代码位置)将从每个文件中读取一个证书。如果您向它提供一个包含多个连接在一起的证书的文件,它实际上只会将文件中的第一个证书验证为叶证书,而完全忽略其他证书。
因此,在您的示例中,您实际所做的是验证foocert.pem 为叶证书,因为它是roguechain.pem. foocert.pem即使带有-purpose sslserver. man x509部分CERTIFICATE EXTENSIONS记录了“SSL 服务器”目的的条件:
SSL Server
The extended key usage extension must be absent or include the "web server authentication" and/or one
of the SGC OIDs. keyUsage must be absent or it must have the digitalSignature, the keyEncipherment set
or both bits set. Netscape certificate type must be absent or have the SSL server bit set.
Run Code Online (Sandbox Code Playgroud)
并且您可以看到您foocert.pem没有扩展密钥用法并且不是 Netscape 类型证书;它确实有密钥用法,同时设置了数字签名和密钥加密位。因此,它通过了测试。
要进行您真正想做的检查,您必须这样做:
openssl verify -CAfile rootcert.pem -untrusted foocert.pem -purpose sslserver roguecert.pem
使用您在初始问题中给出的文件名。基本上,将根 CA 证书作为-CAfile、-CApath或 提供-trusted,中间 CA 证书作为 提供-untrusted,并将叶证书作为最终参数进行验证,这是一个合理的简化。
请注意,传递的文件-untrusted 可以包含多个连接在一起的证书:
-untrusted file
A file of untrusted certificates. The file should contain multiple certificates in PEM format
concatenated together.
Run Code Online (Sandbox Code Playgroud)
如果你想按照代码来确认这一点,每个叶子证书文件都是由load_cert()in加载的apps/apps.c。该函数的回报是X509;X509对象是单个证书。与load_certs()返回的同一文件中的比较STACK_OF(X509)- 这就是 OpenSSL 通常用于原始证书链的内容。
小智 5
我怀疑 openssl 只查看它在 roguecert.pem 文件中找到的第一件事,这是 foocert.pem 的有效内容。(要向自己证明,请将 args 交换为 cat。)要验证证书链,请使用以下方法提供链中不受信任的证书:
-untrusted file
A file of untrusted certificates. The file should contain multiple
certificates in PEM format concatenated together.
Run Code Online (Sandbox Code Playgroud)