假设我有三个证书(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)签名,则会出现异常。这正是我想要的。
答案 0 :(得分:28)
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链,所以最好调试并逐步完成代码。