.net - 如何确保我们从链中获得最顶层的根 CA 证书?

标签 .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 委托(delegate)接收 X509Chain,后者又包含构成链的证书数组。我不确定我们是否可以依靠数组中元素的顺序来确定顶级根 CA。

我找到了 thisthis ,但第一个依赖于 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/

相关文章:

.net - .NET 应用程序的 Outlook 导航栏控件

C#,使用反射获取switch中的每个case名称

java - TLS 服务器接受来自客户端的连接,即使服务器信任库中不存在客户端证书?为什么?

代理通行证的 SSL 证书?

ssl - 同一服务器(IP 地址)的多个域 SSL 证书

java - 商业产品组件的安全 HTTP 通信

c# - 使用正则表达式从此字符串获取字符串模式

c# - 如何在当前项目的代码路径中找到?

ssl - 如何在 Nginx 中为自定义位置设置双向 SSL?

c# - WCF 服务 web.config 调整以更改生成的 wdl