对于其他的,您可能想要生成自己的测试 CA。
证书链不包含受信任的证书颁发机构
您可以使用您的测试 CA(或自签名证书)生成测试证书,但让默认系统 CA 列表用于验证。您的测试客户端应该无法验证该证书。
在激活日期之前使用,在到期日期之后使用
您可以使用您的测试 CA 生成测试证书,notBefore/notAfter 日期使当前日期无效。然后,使用您的测试 CA 作为受信任的 CA 进行验证:您的测试客户端应该因为日期而无法验证证书。
已被撤销
这可能是最难设置的,具体取决于撤销的发布方式。同样,使用您自己的测试 CA 生成一些您已立即撤销的测试证书。一些工具期望在一组受信任的 CA 旁边配置一组 CRL 文件。这需要对测试本身进行一些设置,但很少进行在线设置:这可能是最简单的。您还可以设置本地在线撤销存储库,例如使用 CRL 分发点或 OCSP。
PKI 测试可能比一般情况下更复杂。完整的测试套件需要对规范有相当好的理解(RFC 5280)。实际上,您可能需要检查所有中间证书的日期,以及链中每个证书的各种属性(例如密钥使用、基本约束……)。
通常,客户端库将验证过程分为两个操作:验证证书是否可信(PKI 部分)和验证它是否已颁发给您要连接的实体(主机名验证部分)。这当然是因为这些是在不同的文档中指定的(分别为 RFC 3280/5280 和 RFC 2818/6125)。
从实际的角度来看,使用 SSL 库时要检查的前两点是:
- 当您连接到已知主机但使用证书无效的不同标识符(例如其 IP 地址而不是主机)时会发生什么?
- 当您连接到您知道无法通过任何默认的受信任锚点(例如,自签名证书或来自您自己的 CA)验证的证书时会发生什么。
在这两种情况下都应该发生连接/验证失败。如果一切正常,没有实现完整的 PKI 测试套件(需要一定的专业知识),通常情况下您需要检查该 SSL 库的文档以了解如何打开这些验证。
除了错误之外,本文中提到的相当多的问题是由于一些库实现假设由用户知道他们在做什么,而他们的大多数用户似乎已经做出了假设该库默认情况下正在做正确的事情。(事实上,即使库默认做正确的事情,当然也不缺少只想摆脱错误消息的程序员,即使这会使他们的应用程序不安全。)我可以公平地说在大多数情况下,确保启用验证功能就足够了。
至于一些现有实现的状态:
Python:Python 2.x 和 Python 3.x 之间发生了变化。Python 3.2的ssl
模块有一个match_hostname
Python 2.7 没有的方法。urllib.request.urlopen
在 Python 3.2 中也有一个配置 CA 文件的选项,它的 Python 2.7 等效项没有。(话虽这么说,如果没有设置,验证将不会发生。我不确定主机名验证。)
Java:默认情况下,对 PKI 和主机名的验证都是打开的HttpsUrlConnection
,但在直接使用时不会对主机名进行验证SSLSocket
,除非您使用的是 Java 7 并且您已经配置了它的SSLParameters
使用setEndpointIdentificationAlgorithm("HTTPS")
(例如)。
PHP:据我所知,fopen("https://.../")
根本不会执行任何验证。