我们销售的产品设置了几个web服务,每个服务在一堆端点上,其中一些甚至支持任意子fqdn。我的意思是,如果端点是foo.example.com
,那么它也服务于*.foo.example.com
。
无论如何,我们想提供的功能之一是能够接受任何一堆证书和私钥,按端点对它们进行排序,验证它们并将它们推送到不同的服务。这意味着我们可以接受包含所有端点和san及其私钥的证书的单个文件和直至CA根的整个链之间的任何内容;还有一堆文件,包含任何东西,并找出它们是否是证书,哪种证书,适用于哪里,等等。我们决定这样做,因为证书已经足够难了,所以我们想从客户端移除做所有这些事情的负担。
我们这样做的方式如下:对于每个端点,我们找到一个覆盖它的证书。然后我们找到匹配的键,并将链返回到顶部。
我的问题是最后一部分的最后一部分。当我们找到一个带有CA位的自签名证书时,我们认为我们找到了链的顶部。想象一下,当昨天一位同事递给我一个根证书时,我有多么惊讶,上面写着:
Issuer: O = Digital Signature Trust Co., CN = DST Root CA X3
Subject: C = US, O = Internet Security Research Group, CN = ISRG Root X1
这是让我们加密根证书不是自签名,而是由其他人签名。这样可以吗?
解决方案的唯一提示是后来我在证书中发现的:
Authority Information Access:
CA Issuers - URI:http://apps.identrust.com/roots/dstrootcax3.p7c
我应该(自动)下载该文件以完成链构建吗?或者我应该在系统的可信根中搜索C = US, O = Internet Security Research Group, CN = ISRG Root X1
证书?请注意,因为我们的产品可以安装在黑暗的网站,前者不是一个真正的选择。
答案相当复杂,我将尝试制作一个项目符号列表:
-
验证链时,始终首先使用信任存储。例如,最近的linux在
/etc/ssl
中有一个。这意味着,如果你像我一样从最终证书回溯,你应该首先在信任存储中寻找发行者,然后在(不受信任的)提供的链中寻找发行者,否则你最终会遇到与openssl-1.0.2
相同的错误。 -
一旦以这种方式验证,提供最大兼容性的原始链。这是因为原始LE链的"根"证书要么被新的替换(自2015年以来!)LE使用以前的算法自签名根,或者使用去年过期的丢失的"真实"根进行验证。这似乎是非常老的Android系统的情况(因此LE首先默认提供此链的原因)。
-
您总是可以要求LE提供具有SS根证书的新链,但如上所述,这是不太兼容的。如果你可以没有2015年以前的客户,这可能是最好的方法。