我很好奇单行openssl
命令行接口的调用是否有能力执行完整的OCSP验证协议,例如查询链中的所有OCSP响应服务器以确认证书的当前有效性。
为了查看是否是这样,我将 正如@pepo 的回答中所解释的,服务器证书链是在 RFC 5246 中指定的基本 TLS1.2 握手的一部分发送的(下面的更新中有更多详细信息)-CAfile
选项指定为/dev/null
,希望这样可以避免使用任何缓存的证书来代替查找:
# openssl s_client -CAfile /dev/null -connect www.equifaxsecurity2017.com:443
这给出了输出:
CONNECTED(00000003)
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = GeoTrust Inc., OU = Domain Validated SSL, CN = GeoTrust DV SSL CA - G3
verify return:1
depth=0 CN = www.equifaxsecurity2017.com
verify return:1
---
Certificate chain
0 s:/CN=www.equifaxsecurity2017.com
i:/C=US/O=GeoTrust Inc./OU=Domain Validated SSL/CN=GeoTrust DV SSL CA - G3
1 s:/C=US/O=GeoTrust Inc./OU=Domain Validated SSL/CN=GeoTrust DV SSL CA - G3
i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
<omitted>
-----END CERTIFICATE-----
subject=/CN=www.equifaxsecurity2017.com
issuer=/C=US/O=GeoTrust Inc./OU=Domain Validated SSL/CN=GeoTrust DV SSL CA - G3
---
No client certificate CA names sent
....
看起来好像 不!这是不正确的!openssl
在没有任何缓存文件帮助的情况下找到了链中的所有三个链接,因此必须通过 Internet 与代理 (1) GeoTrust DV SSL CA - G3和 (2) GeoTrust Global CA进行通信,以构建链。那是对的吗?
是否openssl
还通过向三个 OCSP 响应者中的每一个发出适当的 OCSP 请求来验证链?
(我的猜测是“不”。我也知道它openssl ocsp ...
可以与证书上的手动文本操作结合使用,以一次执行一个链接的 OSCP 验证。但是,这似乎是合理的,甚至更可取的是,这openssl
将被写入执行完整的 OCSP 验证,这就是我要问的原因。)
2017 年 9 月 14 日更新:
感谢@pepo 的回答“SSL 服务器(如果配置正确)将发送证书链(根 CA 证书除外)”,我查找了 RFC 5246 并找到了“7.4.2 服务器证书”部分,它解释了“服务器”的内容证书”部分的 TLS1.2 握手:
这是证书的序列(链)。发件人的
证书必须在列表中排在第一位。后面的每个证书必须直接证明它前面的证书。因为证书验证要求根密钥是独立分发的,所以可以从链中省略指定根证书颁发机构的自签名证书,假设远程端必须已经拥有它才能在任何情况下验证它。
此外,感谢@pepo 对该-crl_check_all
选项的回答,我尝试了这一点并得到了以下输出:
CONNECTED(00000003)
depth=0 CN = www.equifaxsecurity2017.com
verify error:num=3:unable to get certificate CRL
verify return:1
depth=1 C = US, O = GeoTrust Inc., OU = Domain Validated SSL, CN = GeoTrust DV SSL CA - G3
verify error:num=3:unable to get certificate CRL
它因错误而失败unable to get certificate CRL
。事实证明这并不重要,因为所选网站启用 了OCSP 装订。
如果我们不-crl_check_all
执行CRL 检查,而是
添加-status
请求OCSP 装订的选项,则会收到以下输出:
CONNECTED(00000003)
<stuff omitted omitted>
OCSP response:
======================================
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: CE2C8B1E8BD2300FD1B15446E9B594254949321B
Produced At: Sep 10 11:12:45 2017 GMT
Responses:
Certificate ID: ...
Cert Status: good
This Update: Sep 10 11:12:45 2017 GMT
Next Update: Sep 17 11:12:45 2017 GMT
Signature Algorithm: sha1WithRSAEncryption
<stuff omitted>
这表明在服务器端启用了 OCSP 装订,但它似乎只对第一个(叶)证书启用,而不是对第二个证书启用。(无论如何,必须独立验证自签名的第三个证书)。因此,要验证第二个证书,必须使用CRL-checking或OCSP-request-response。由于此特定授权链未启用CRL 检查,因此只剩下OCSP-request-response。
感谢@pepo 的回复,让我更了解TLS1.2协议和这些验证授权的方法(按历史顺序列出)之间openssl
的关系:
- CRL(证书撤销列表)检查
- OSCP 请求和响应
- OCSP 装订
但是,也提出了一个新问题:
- 关于在“服务器证书”消息步骤期间服务器发送的OCSP 装订响应以及链中的证书 - 这具有需要验证的签名信息(从下一级开始)。这个签名信息在处理过程中是否真的得到了验证
openssl ... -status
?
更新:2017 年 9 月 15 日
根据这个答案
以及下面@dave_thompson_085 的评论(他已经查看了源代码) ,对“在处理过程中是否真的验证了这个签名信息openssl ... -status
?”这个问题的安全答案似乎是否定
的。
是否令人困惑?是的!奇怪的是,“OpenSSL Cookbook (feistyduck, Ivan Ristić)” 对这个问题异常不清楚, 没有显示验证签名的明确方法,同时也没有明确说明签名是否已被验证。相反,对于其他两种类型的撤销检查:
“OpenSSL Cookbook”显示了明确的方法(食谱),以进一步使用openssl
. 推断“OpenSSL Cookbok”不包含完全验证装订的 OCSP 响应的配方是一个非常人为的错误,因为它没有必要。
恕我直言,OpenSSL(或任何类似库)将非常负责按照以下优先顺序包含顶级文档
- (1) 说明 OpenSSL 不提供对 TLS+授权的黑盒解决方案,
- (2) 关于它提供的解决方案的有限部分的解释(例如,没有授权检查的 TLS 握手),
- (3) 有关组装 OpenSSL 组件以完成授权检查解决方案的配方的文档。
误解很容易传播。就在几天前,我正在尝试编写一个简单的程序来从我的 Linux Ubuntu PC 发送通知邮件。标准 Python 版本(版本 2 和 3)包括一个 SMTP 和一个“实现”TLS1.2 的 SSL 库。我可以在 10 分钟内编写程序并在调试器中完成它。我可以看到从 python SSL 库到 OpenSSLhandshake()
函数的调用,并假设handshake()
必须处理所有授权检查,基于 SSL 库和 SMTP 库在不包括授权检查的情况下不会被释放的假设。奇怪的是,SSL 库中的调用代码包含一个后handshake()
检查,以确保接收到的证书名称与被调用服务器的名称匹配。"handshake()
已经处理了所有的签名验证,等等?”,我想。这个疑问开始了剥离 TLS 安全洋葱层的旅程,从那以后我一直哭泣不已。
我不想尝试重新发明轮子,无论如何这可能会摇摆不定。然而,我似乎找不到任何可用的轮子。然后去哪儿?