有一个自签名的根CA证书rootcert.pem,扩展名如下:
X509v3 extensions:
X509v3 Key Usage:
Certificate Sign
X509v3 Basic Constraints:
CA:TRUE
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
foocert.pem将CA标志设置为false&其密钥用法不允许证书签名。但是,让我们说,foocert.pem签署了一个rougecert.pem。
形成一个foocert& amp;的证书链。 roguecert:
cat foocert.pem roguecert.pem > roguechain.pem
使用openssl验证验证。验证成功:
$ openssl verify -CAfile rootcert.pem roguechain.pem
roguechain.pem: OK
使用x509_strict验证,仍然成功:
$ openssl verify -x509_strict -CAfile rootcert.pem badchain.pem
badchain.pem: OK
让我们说系统只信任根CA证书。对等体提供其证书链,其中一个中间证书不应该是CA(CA设置为false,密钥用法不允许证书签名),仍然openssl标记链是好的吗?
如何让openssl不信任这样的链?
答案 0 :(得分:5)
原来的答案证明是错的,所以这是另一个:)
看起来openssl verify只进行证书链验证,并且不检查任何标志(即使设置了正确的用途)。但是,当您实际执行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)
答案 1 :(得分:2)
我怀疑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.
答案 2 :(得分:2)
(编辑:刚刚注意到我的回答是一个更长更详细的Chris Lesner版本,我会投票给他,但我还没有这里的代表:>)
我认为你在这里仍然走错了路。我认为实际问题是“验证”不会以这种方式验证单个文件中的链。
“验证”的最后一个参数列为[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.
您可以传递多个文件 - 但每个文件都将被验证为单个叶子证书,与其他文件无关。它并不是绝对明确的,但它暗示(我可以告诉你事实上是这样的;请参阅下面的代码位置了解详细信息)将从每个文件中读取一个证书。如果您将包含多个证书连接在一起的文件提供给它,它实际上只是将该文件中的第一个证书验证为叶证书,并完全忽略其他证书。
因此,在您的示例中,您实际执行的操作是将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.
您可以看到您的foocert.pem
没有扩展密钥用法且不是Netscape类型证书;它确实具有密钥用法,同时设置了数字签名和密钥加密位。因此,它通过了测试。
要做你真正想做的检查,你必须这样做:
openssl verify -CAfile rootcert.pem -untrusted foocert.pem -purpose sslserver roguecert.pem
使用您在初始问题中提供的文件名。基本上,合理的简化是说您提供根CA证书为-CAfile
,-CApath
或-trusted
,中间CA证书为-untrusted
,以及叶证书(s) )被确认为最终论据。
请注意,作为-untrusted
传递的文件可以包含连接在一起的多个证书:
-untrusted file
A file of untrusted certificates. The file should contain multiple certificates in PEM format
concatenated together.
如果您想按照代码进行确认,每个叶证书文件都由load_cert()
apps/apps.c
加载。该函数的返回值为X509
; X509
个对象是单个证书。与同一文件中的load_certs()
进行比较,该文件返回STACK_OF(X509)
- 这就是OpenSSL通常用于原始证书链的内容。