如何确保我们从链中获得最高的根CA证书?

时间:2017-04-12 02:16:35

标签: .net ssl ssl-certificate x509certificate2

我使用此代码评估根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证书:

Certificate Chain

(是的,我知道StartCom已被摘牌 - 我将在本周晚些时候处理。)

ServerCertificateValidationCallback委托收到X509Chain,而Extension.CertificateAuthority又包含构成链的证书数组。我并不相信我们可以依赖这些元素'在数组中按顺序确定顶级根CA.

我找到thisthis,但第一个依赖于Magic Strings™,第二个依赖于可选字段。而且上面的True属性也不会缩小范围。我们可以看到,链中的两个证书将此属性设置为X509Certificate2

Certificate.IssuerThumbprint的公共财产似乎不包括我们可以用来可靠地识别链中发行人的任何内容。最方便的是X509ChainPolicy.ExtraStore或类似的东西。

显然,这些信息是以某种方式提供的,因为该链是首先建立的。而且我很难考虑这种简单功能在API中被忽略的可能性。

我必须在某个地方错过它。

- 编辑 -

我找到了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)) 属性,它似乎包含所有证书,除了我们之后的那个。从这里开始,这是一个简单的排除问题:

ideally_the_result : dependencies
<tab>the commands
<tab>the commands
<tab>the commands

这是在链中查找顶级根CA的可靠方法吗?

1 个答案:

答案 0 :(得分:1)

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;
}