C# 如何验证 Root-CA-Cert 证书 (x509) 链?

Posted

技术标签:

【中文标题】C# 如何验证 Root-CA-Cert 证书 (x509) 链?【英文标题】:C# How can I validate a Root-CA-Cert certificate (x509) chain? 【发布时间】:2011-11-11 23:58:24 【问题描述】:

假设我有三个证书(Base64 格式)

Root
 |
 --- CA
     |
     --- Cert (client/signing/whatever)

如何在 C# 中验证证书和证书路径/链? (所有这三个证书可能不在我的计算机证书存储中)

编辑:BouncyCastle 具有验证功能。但我尽量不使用任何第三方库。

    byte[] b1 = Convert.FromBase64String(x509Str1);
    byte[] b2 = Convert.FromBase64String(x509Str2);
    X509Certificate cer1 = 
        new X509CertificateParser().ReadCertificate(b1);
    X509Certificate cer2 =
        new X509CertificateParser().ReadCertificate(b2);
    cer1.Verify(cer2.GetPublicKey());

如果 cer1 没有被 cert2(CA 或 root)签名,就会出现异常。这正是我想要的。

【问题讨论】:

【参考方案1】:

X509Chain 类就是为此而设计的,您甚至可以自定义它如何执行链构建过程。

static bool VerifyCertificate(byte[] primaryCertificate, IEnumerable<byte[]> additionalCertificates)

    var chain = new X509Chain();
    foreach (var cert in additionalCertificates.Select(x => new X509Certificate2(x)))
    
        chain.ChainPolicy.ExtraStore.Add(cert);
    

    // You can alter how the chain is built/validated.
    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
    chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;

    // Do the validation.
    var primaryCert = new X509Certificate2(primaryCertificate);
    return chain.Build(primaryCert);

如果您需要,X509Chain 将在Build() == false 之后包含有关验证失败的其他信息。

编辑:这只会确保您的 CA 有效。如果要确保链相同,可以手动检查指纹。您可以使用以下方法确保认证链正确,它期望链中的顺序:..., INTERMEDIATE2, INTERMEDIATE1 (Signer of INTERMEDIATE2), CA (Signer of INTERMEDIATE1)

static bool VerifyCertificate(byte[] primaryCertificate, IEnumerable<byte[]> additionalCertificates)

    var chain = new X509Chain();
    foreach (var cert in additionalCertificates.Select(x => new X509Certificate2(x)))
    
        chain.ChainPolicy.ExtraStore.Add(cert);
    

    // You can alter how the chain is built/validated.
    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
    chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;

    // Do the preliminary validation.
    var primaryCert = new X509Certificate2(primaryCertificate);
    if (!chain.Build(primaryCert))
        return false;

    // Make sure we have the same number of elements.
    if (chain.ChainElements.Count != chain.ChainPolicy.ExtraStore.Count + 1)
        return false;

    // Make sure all the thumbprints of the CAs match up.
    // The first one should be 'primaryCert', leading up to the root CA.
    for (var i = 1; i < chain.ChainElements.Count; i++)
    
        if (chain.ChainElements[i].Certificate.Thumbprint != chain.ChainPolicy.ExtraStore[i - 1].Thumbprint)
            return false;
    

    return true;

我无法对此进行测试,因为我没有完整的 CA 链,因此最好调试并逐步执行代码。

【讨论】:

谢谢。但我故意将不同的颁发者证书放在“additionalCertificates”中,结果是“true”:( 谢谢乔纳森。但不工作。看起来 chain.Build 正在验证证书的有效性。不是证书路径。只要证书有效(证书链/路径错误),结果就为真。指纹方法不起作用,因为所有指纹都不同(即使在正确的路径/链中) @Jacob,这就是我手动验证指纹的原因,正如我所说,逐步完成代码的新部分。我还在if (chain.Build) 位中打错了字。更新它。 primaryCertificate 是最终证书,其他证书是 CA 到 root

以上是关于C# 如何验证 Root-CA-Cert 证书 (x509) 链?的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用本地 CRL 文件(C#)的验证过程中检查客户端证书吊销

如何通过 HttpsURLConnection 使用证书身份验证?

C#发送邮件异常:根据验证过程,远程证书无效

C#在客户端验证数字证书(Certificate)

c# https请求忽略证书验证_各种编程语言忽略http的SSL证书认证

以编程方式使用证书身份验证配置 WCF 服务客户端