我正在使用此代码评估链中每个证书的根 CA 状态:
Function GetRootCaCertificates(Chain As X509Chain) As IEnumerable(Of X509Certificate2)
With Chain.ChainElements.Cast(Of X509ChainElement)
With .Select(Function(Element As X509ChainElement) Element.Certificate)
Return .Where(Function(Certificate As X509Certificate2)
With Certificate.Extensions.Cast(Of X509Extension)
With .Where(Function(Extension As X509Extension) TypeOf Extension Is X509BasicConstraintsExtension)
With .Cast(Of X509BasicConstraintsExtension)
Return .Where(Function(Extension As X509BasicConstraintsExtension) Extension.CertificateAuthority = True).Count > 0
End With
End With
End With
End Function).ToList
End With
End With
End Function
它运行良好,但在当前情况下它返回两个 StartCom 证书:
(是的,我知道 StartCom 已被除名——我将在本周晚些时候处理这件事。)
ServerCertificateValidationCallback
委托(delegate)接收 X509Chain
,后者又包含构成链的证书数组。我不确定我们是否可以依靠数组中元素的顺序来确定顶级根 CA。
我找到了 this和 this ,但第一个依赖于 Magic Strings™,第二个依赖于可选字段。上面的 Extension.CertificateAuthority
属性也没有足够地缩小范围。正如我们所见,链中的两个证书将此属性设置为 True
。
X509Certificate2
的公共(public)属性似乎不包含我们可以用来在链中可靠地识别其颁发者的任何内容。最方便的是 Certificate.IssuerThumbprint
或类似的东西。
显然,此信息以某种方式可用,因为链是首先构建的。我很难考虑 API 中忽略了这种简单功能的可能性。
我一定是在某个地方遗漏了它。
--编辑--
我找到了 X509ChainPolicy.ExtraStore
属性,它似乎包含所有证书除了我们想要的证书。从这里开始,这是一个简单的排除问题:
Dim oCertificates As List(Of X509Certificate2)
Dim oThumbprints As IEnumerable(Of String)
oThumbprints = Chain.ChainPolicy.ExtraStore.Cast(Of X509Certificate2).Select(Function(Certificate As X509Certificate2) Certificate.Thumbprint)
oCertificates = Chain.ChainElements.Cast(Of X509ChainElement).Select(Function(Element As X509ChainElement) Element.Certificate).ToList
oCertificates.RemoveAll(Function(Certificate As X509Certificate2) oThumbprints.Contains(Certificate.Thumbprint))
这是在链中找到顶级根 CA 的可靠方法吗?
最佳答案
ChainElements 按从最叶到最根的顺序排列。因此,只要您没有收到 PartialChain 错误,它就是最后一个 ChainElement 的证书。
private static X509Certificate2 GetRootCertificate(X509Chain chain)
{
// Assumes that chain.Build was already called
X509ChainElement chainElement = chain.ChainElements[chain.ChainElements.Count - 1];
foreach (X509ChainStatus status in chainElement.ChainElementStatus)
{
if (status.Status == X509ChainStatusFlags.PartialChain)
{
return null;
}
}
return chainElement.Certificate;
}
关于.net - 如何确保我们从链中获得最顶层的根 CA 证书?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43359089/