强制 Chrome 在 TLS 期间发送链中的所有证书
Posted
技术标签:
【中文标题】强制 Chrome 在 TLS 期间发送链中的所有证书【英文标题】:Force Chrome to send all certificates in chain during TLS 【发布时间】:2018-09-06 11:32:02 【问题描述】:我编写了一个 TLS 代码,它在 Java 中进行相互身份验证,因此客户端在服务器发送其证书后发送其证书。我想通过从客户端到服务器端的 OCSP 验证证书链中的所有证书。
我已经编写了我的循环逻辑,假设最后一个证书是链中的根 (CA) 证书,并且不发送任何 OCSP 查询;
int certificateChainSize= x509Certificates.length;
// Verifies certificate chain respectively (issuer certificate required).
CertificateResult response = null;
try
for (int i = 0; i < certificateChainSize-1 ; i++)
response = client.verify(x509Certificates[i], x509Certificates[i+1]);
catch (OcspException e)
e.printStackTrace();
当我测试 TLS 并获得 Wireshark 捕获时,我意识到 Google Chrome 作为客户端一直在发送没有 root 的证书链。因此;由于循环逻辑,没有查询中间证书,因为我的代码假设中间证书是根证书。
如何强制客户端发送证书链的所有节点?
谢谢
【问题讨论】:
【参考方案1】:我意识到 Google Chrome 作为客户端一直在发送没有 root 的证书链。
这是完全正常的,也是唯一正确的行为。
根证书是证书验证方本地的信任锚。即使它是发送的,在验证证书时也应该忽略它,即只应该使用本地信任锚 - 否则中间的人可以只提供他自己的证书链,包括他自己的根证书。这意味着在这种情况下,服务器必须已经在本地拥有根证书,因此客户端不需要发送它。
换句话说:不要试图改变 Chrome 的行为方式,而是调整你对正确行为的期望(和你的代码)。
【讨论】:
那么,如何发送 OCSP 查询以获取中间证书? AFAIK OCSP 请求包含散列的颁发者名称和密钥,但我们没有根的密钥作为颁发者,因为根不存在。 @korayguney:这是与您原来的问题不同的问题(询问如何让 Chrome 发送根目录)。要点是,您不应该首先简单地使用对等方发送的证书,而是使用本地计算的信任链作为基础来验证证书的有效性,因为它可能是例如服务器发送的不相关的证书或不同的信任链是可能的(例如由于交叉签名)。虽然我知道如何在 OpenSSL 中获取这个计算链,但我不知道如何在 Java 中访问它。【参考方案2】:我同意 Steffen 的观点,但为了提供更多事实,TLS 1.3 明确表示:
certificate_list:CertificateEntry 结构的序列(链), 每个都包含一个证书和一组扩展。
和
发件人的证书必须放在第一位 列表中的证书条目。以下每个证书应该 直接证明前一个。因为 证书验证要求分发信任锚 独立地,指定信任锚的证书可以是 从链中省略,前提是支持的对等点已知 拥有任何遗漏的证书。
最后是关于订购:
注意:在 TLS 1.3 之前,每个都需要“certificate_list”排序 证明紧接其前一者的证明书;然而, 一些实现允许一些灵活性。服务器有时 发送当前和不推荐使用的过渡中间体 目的,而其他的只是配置不正确,但这些 尽管如此,仍可以正确验证案例。对于最大 兼容性,所有实现都应该准备好处理 来自任何潜在的无关证书和任意排序 TLS 版本,最终实体证书除外 必须是第一个。
所以 Chrome 正确地应用了这个规范。你需要改变你的结局来应对它。
【讨论】:
以上是关于强制 Chrome 在 TLS 期间发送链中的所有证书的主要内容,如果未能解决你的问题,请参考以下文章
使用网络面板进行分析时强制 Chrome 关闭/重新打开所有 TCP/TLS 连接