如何验证证书是由特定认证机构创建的?

25

我有一个Windows认证机构,我正在使用它通过 .net / c# 发放客户端身份验证证书。我已经成功地通过调用认证机构的API来进行编程, 从而能够发放证书。在设置客户端时,我会发放新的证书。

运行时,这些客户端将证书附加到向我的服务器发送的请求中。如何通过编程验证X509Certificate2是由我的证书颁发机构的根证书签名的(并拒绝由任何其他来源签名的证书)?


1
应该在security.se上 (或许)。 - Woot4Moo
2
为什么?我的问题是如何验证登录代码... - Jeffrey Meyer
你找到编写这个代码的方法了吗? - MiguelM
3个回答

43
我已经做过这件事情很多次。以下是您可以使用的简单代码。
在“if (!isChainValid)”块中的部分是为了生成漂亮的错误消息。如果不想要,您不必使用它,但如果无法构建链,则应引发错误。链元素对于检查根非常重要。
X509Certificate2 authority = GetAuthorityCertificate();
X509Certificate2 certificateToValidate = GetCertificateToValidate();

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

// This part is very important. You're adding your known root here.
// It doesn't have to be in the computer store at all. Neither certificates do.
chain.ChainPolicy.ExtraStore.Add(authority);

bool isChainValid = chain.Build(certificateToValidate);

if (!isChainValid)
{
    string[] errors = chain.ChainStatus
        .Select(x => String.Format("{0} ({1})", x.StatusInformation.Trim(), x.Status))
        .ToArray();
    string certificateErrorsString = "Unknown errors.";

    if (errors != null && errors.Length > 0)
    {
        certificateErrorsString = String.Join(", ", errors);
    }

    throw new Exception("Trust chain did not complete to the known authority anchor. Errors: " + certificateErrorsString);
}

// 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)
{
    throw new Exception("Trust chain did not complete to the known authority anchor. Thumbprints did not match.");
}

@ChrisBenard 验证证书是否与已知根证书匹配的代码真的没问题吗?应该像这样执行该代码,并且几乎总是返回 true:chain.ChainElements.Cast<X509ChainElement>().All(x => x.Certificate.Thumbprint != "XX"); - Ogglas
1
如果证书没有过期/吊销等问题,由于使用了“X509VerificationFlags.AllowUnknownCertificateAuthority”,它将返回true。后续通过指纹的检查是必要的,以检查您已经使用“ExtraStore.Add()”添加到链中的授权。 - Chris Benard
1
我有根证书和中间证书(由根证书签名),需要验证客户端证书,该证书由中间证书签名。在这种情况下,我需要将根证书和中间证书添加到额外存储器中,并需要检查哪个证书的指纹? - Varsh
1
@Varsh听起来您需要添加根证书和中间证书,并检查根证书的指纹。 - Chris Benard
所以我需要添加所有中间证书,如果我只有根证书,我将无法进行检查? - Guilherme de Jesus Santos
显示剩余6条评论

1

0
如果您说您有一个(自签名的)证书,那么您唯一的选择是在服务器上保留此根证书(当然不包括私钥),并对其进行证书验证过程。这与Web客户端验证服务器证书链的情况相似。

1
我正好有这种情况。我会澄清我的问题,但我正在寻找在C#中验证签名所需的特定代码。 - Jeffrey Meyer
@Jeffrey 我知道在我们的SecureBlackbox for .NET中如何完成此操作,但不知道在纯.NET Framework中如何完成。 - Eugene Mayevski 'Callback
可能有更好的方法,但请查看X509Chain类。文档示例显示了遍历链并在沿途检查每个元素的代码。 - Frank Boyne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接