0

我有一个根证书和一个叶子。叶具有指向有效在线位置的 CRL URL OID 扩展。这样做:

certutil -verify .\leaf.cer

失败了

错误:验证叶证书吊销状态返回吊销功能无法检查吊销,因为吊销服务器处于脱机状态。0x80092013 (-2146885613 CRYPT_E_REVOCATION_OFFLINE)

如果我这样做:

certutil -verify .\leaf.cer .\root.cer

然后验证通过,我看到 CRL 从 Fiddler 中在线提取。

在我的 C# 代码中,我这样做:

X509Chain childCertChain = new X509Chain();
childCertChain.ChainPolicy.ExtraStore.Add(rootCert);
childCertChain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
childCertChain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromSeconds(10);
if (!childCertChain.Build(childCert))
        {
            // The root cert is not in the windows certificate store, that is fine
            if (childCertChain.ChainStatus.Length != 1 || childCertChain.ChainStatus.First().Status != X509ChainStatusFlags.UntrustedRoot)
            {
                throw new Exception("Certificate validation error.");
            }
        }

这会遇到我的异常,即使 chainElements 将正确填充 2 个证书,ChainStatus 也会显示:

OfflineRevocation, RevocationStatusUnknown

我也不会在 Fiddler 中看到任何 Web 请求。我可以通过给定 URL 以编程方式下载 CRL,因此它不是我的调试环境 AFAIK。任何想法如何让 x509Chain.Build 成功?

4

1 回答 1

0

我已经从 PC 上阅读了您的代码并弄清楚了发生了什么:您的根证书在您的系统上不受信任。CERT_E_UNTRUSTEDROOT当根证书不受信任时,Windows CryptoAPI 会抛出。与此同时,CryptoAPI 终止吊销检查并抛出两个附加错误:CRYPT_E_NO_REVOCATION_CHECKCERT_E_UNTRUSTEDROOT,因为跳过了吊销检查。除了不受信任的根,CryptoAPI 会跳过其他检查(例如约束),但不报告它们。一切都是正确的,如预期的那样。

您正在尝试允许不受信任的根,但这样做不正确,因为这样您会跳过其他检查(如上一段所述)并且您的逻辑很容易受到攻击。

您可以在链设置中排除不受信任的根异常,并强制 CryptoAPI 继续验证并在未发现其他错误时返回成功,但我强烈建议不要这样做,因为这样您就可以接受任何类型的 MITM。

你有两个选择:

  1. 使机器(本地系统)信任根证书。这可能是不可能的。
  2. 直接调用CertCreateCertificateChainEngine函数并将您的根证书放入结构的hRestrictedTrust成员中CERT_CHAIN_ENGINE_CONFIG

如果您使用的是 Windows,则第二种方法是最安全可靠的。到目前为止,.NETX509Chain还没有实现这个功能。它需要额外的编码,但没有太多选择。

于 2020-04-08T20:48:35.787 回答