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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#如何验证Root-CA-Cert证书(x509)链?相关的知识,希望对你有一定的参考价值。

假设我有三个证书(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)签名,则会出现异常。这正是我想要的。

答案

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链,所以最好调试并逐步完成代码。

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

如何验证 x509 证书的签名?

Apache HttpClient 4.3 和 x509 客户端证书进行身份验证

使用 node.js 验证带有 CA 证书的 X509 证书

Java X509 证书解析和验证

Grails 中基于 RESTful 证书的 (X509) 登录身份验证

如何配置 WCF 以通过 Internet 使用 x509 证书?