如何从C#中的特定根CA验证证书链

时间:2017-03-06 10:23:22

标签: c# security x509certificate ca

我有一个如下所示的证书链:root CA -> intermediate CA -> client certificate。如何验证“root CA”是否明确创建了收到的证书?

验证整个链条不是问题。这可以这样做:

X509Certificate2 rootCert = new X509Certificate2(rootCertFile);
X509Certificate2 intermediateCert = new X509Certificate2(intermediateCertFile);
X509Certificate2 clientCert = new X509Certificate2(clientCertFile);

chain.ChainPolicy.ExtraStore.Add(rootCert);
chain.ChainPolicy.ExtraStore.Add(intermediateCert);

if(chain.Build(clientCert))
{
    // ... chain is valid
}

此处的问题是证书是针对(Windows)证书存储进行验证的,但我只是想针对特定的根CA验证它。

我还认为可以检查chain.ChainElements是否包含我预期的根CA.但是,如果有人从不同的根CA向我发送有效的链并且只是添加了我期望的根CA呢?

1 个答案:

答案 0 :(得分:2)

证书链API检查每个元素是否签署了前面的元素,因此没有人可以在最后添加根CA(假设您没有使用具有MD5签名的384位RSA密钥,在这种情况下,他们可以伪造你的签名。)

您可以编码任何您喜欢的额外支票,例如您知道您的链条都不会超过长度3(尽管您可能只是在根CA的X509基本约束扩展中对其进行了编码)。

if (!chain.Build(cert))
{
    return false;
}

if (chain.ChainElements.Length > 3)
{
    return false;
}

X509Certificate2 chainRoot = chain.ChainElements[chain.ChainElements.Length - 1].Certificate;

return chainRoot.Equals(root);

如果您愿意,最后一行可以是return root.RawData.SequenceEquals(chainRoot.RawData);(确保它们具有相同的字节)。

有些注意事项:

  • 当你调用X509Chain.Build()时,它通过X509ChainElement返回的每个X509Certificate2对象都是一个新对象。您可能希望处理任何未返回的对象(可能全部都是这些对象)。
  • 即使chain.Build返回false,它也会填充ChainElements数组,以便您检查原因。
  • X509Chain对象本身是Disposable,你可能想要它(你可能已经在你的代码片段之外做了)。
  • 处置链不会处理任何创建的证书,因为您可能已经持有对象引用。