C#-验证由正确的根签名的客户端证书

时间:2018-10-19 10:47:20

标签: c# ssl certificate

我知道这个争论有很多问题,但是我已经坚持了几天,所以我在这里。 我有一个根证书和一个客户端证书。我需要在C#Web API项目中复制命令openssl verify -CAfile ca.pem client.pem的作用。

这是我现在所知道的(希望它是真的):

  • Verify()方法实际上验证证书是由授权机构签名的。就像格式控件一样。哪位大律师在证书上签字都没有关系。
  • X509 Chain是必经之路。将CA证书添加到其他商店中,因为我不会将证书安装到Windows中。然后构建通过客户端证书的证书。让魔术发生吧!不幸的是,我在配置上遇到了一些问题。

让我更清楚地举例说明

private bool VerifyCertificate(X509Certificate2 client)
{
    X509Chain chain = new X509Chain();
    var stringCert = WebConfigurationManager.AppSettings["CACertificate"];
    var byteCert = Encoding.ASCII.GetBytes(stringCert);
    var authority = new X509Certificate2(byteCert);

    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
    chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;

    chain.ChainPolicy.ExtraStore.Add(authority);

    // Do the preliminary validation.
    if (!chain.Build(client))
        return false;

    return true;
}

在此示例中,程序返回false。该构建未通过。我确定问题出在ChainPolicy properties上,所以我尝试了另一种配置

chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
chain.ChainPolicy.VerificationTime = DateTime.Now;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0);

但是这个不会验证任何内容,实际上,使用我的ca cert方法会返回true并使用另一个ca证书(我没有用它来签署我的客户端证书),该方法还会返回true

我搜索了C#的OpenSSL包装器,发现了它,但不幸的是它是基于旧库的,并且回购协议也不再被处理。而且,如果可能的话,我将仅使用.net框架即可实现自己的目标。

伙计们,快速回顾一下。我想检查的是,只有由我的ca证书确定的证书才能通过验证,所有其他证书都必须停止。

在此先感谢您的帮助

2 个答案:

答案 0 :(得分:0)

ExtraStore不受限制,它提供了额外的证书来帮助完成链接。它不提供信任数据。

要确定证书是否由您想要的CA颁发,您需要执行以下操作:

private static readonly X509Certificate2 s_trustedRoot = ObtainTheRoot();
private static readonly byte[] s_normalizedRoot = s_trustedRoot.RawData;

private bool VerifyCertificate(X509Certificate2 candidate)
{
    X509Chain chain = new X509Chain();
    // set all the things you need to set to make it build

    if (!chain.Build(candidate))
        return false;

    // Check that the root certificate was the expected one.
    X509ChainElementCollection elements = chain.ChainElements;
    return elements[elements.Count - 1].Certificate.RawData.SequenceEqual(s_normalizedRoot);
}

我假设它的证书和规范化字节形式将其提升为静态,前提是假设一旦过程开始它们就不会改变。如果证书可以动态更改,则应进行相应调整。

答案 1 :(得分:0)

找到问题。 就我而言,这是正确的答案。

 private bool VerifyCertificate(X509Certificate2 client)
    {
        X509Chain chain = new X509Chain();
        var stringCert = WebConfigurationManager.AppSettings["CACertificate"];
        var byteCert = Encoding.ASCII.GetBytes(stringCert);
        var authority = new X509Certificate2(byteCert);

        chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
        chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;

        chain.ChainPolicy.ExtraStore.Add(authority);

        // Do the preliminary validation.
        if (!chain.Build(client))
            return false;

        // This piece makes sure it actually matches your known root
        var valid = chain.ChainElements
            .Cast<X509ChainElement>()
            .Any(x => x.Certificate.Thumbprint == authority.Thumbprint);

        if (!valid)
            return false;

        return true;
    }

现在,调试应用程序我有一些注意事项:

  1. .Build()方法应该做什么?

我的意思是,使用由ca签名的证书或使用自签名证书,方法始终返回true,但是如果我使用受信任的证书,它将在chain.ChainElements内添加证书否则,不添加任何内容。

我需要了解这一点,但是我所做的所有测试都表明该方法有效