如何针对X509Certificate2Collection链验证X509Certificate2

Kei*_*ith 10 .net x509certificate single-sign-on saml-2.0 pkcs#7

我正在编写一个SAML 2.0响应解析器来处理ASP.Net中的POST身份验证(在C#和MVC中,但这不太相关).

所以我有一个.p7b要验证的文件,可以读入一个X509Certificate2Collection和一个示例断言 - 一个基本的64位编码的SAML响应.

理想情况下,我想使用内置的WSSecurityTokenSerializer,但失败了,所以我正在寻找一种有效的方法.

我正在直接读取XML:

// get the base 64 encoded SAML
string samlAssertionRaw = GetFromHttpRequest();

// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml(samlAssertionRaw);

// use a namespace manager to avoid the worst of xpaths
var ns = new XmlNamespaceManager(assertion.NameTable);
ns.AddNamespace("samlp", @"urn:oasis:names:tc:SAML:2.0:protocol");
ns.AddNamespace("saml", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);

// get the signature XML node
var signNode = assertion.SelectSingleNode(
    "/samlp:Response/saml:Assertion/ds:Signature", ns);

// load the XML signature
var signedXml = new SignedXml(assertion.DocumentElement);
signedXml.LoadXml(signNode as XmlElement);

// get the certificate, basically:
// signedXml.KeyInfo.OfType<KeyInfoX509Data>().First().
//     Certificates.OfType<X509Certificate2>().First()
// but with added checks
var certificate = GetFirstX509Certificate(signedXml);

// check the key and signature match
if (!signedXml.CheckSignature(certificate, true))
{
    throw new SecurityException("Signature check failed.");
}

// go on and read the SAML attributes from the XML doc
Run Code Online (Sandbox Code Playgroud)

该批次有效,但它所做的只是检查X509Certificate2SAML响应中的签名和公钥是否匹配.它不会以任何方式验证它的来源,我需要在接受SAML身份验证之前执行此操作.

似乎有两种方法可以检查SAML响应中找到的证书 - 我可以做certificate.Verify()或者我可以使用签名进行检查signedXml.CheckSignature(certificate, false).

然而两者都返回假.

我认为这是因为他们正在检查机器商店或可能在线(我不知道如何检查).我想根据X509Certificate2Collection.p7b文件中检索到的内容来检查它们- 应该忽略机器上注册的证书,只.p7b检查证书.

似乎没有任何方法可以传递X509Certificate2CollectionVerify或者CheckSignature方法.

这是对SAML响应进行的正确检查吗?

有没有办法以.p7b我想要的方式使用证书?

Joã*_*elo 5

您是否尝试过使用自定义X509Chain配置来ExtraStore在验证过程中搜索证书.类似于以下内容:

// Placeholder for the certificate to validate
var targetCertificate = new X509Certificate2();
// Placeholder for the extra collection of certificates to be used
var certificates = new X509Certificate2Collection();

var chain = new X509Chain();

chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.ExtraStore.AddRange(certificates);

bool isValidCertificate = chain.Build(targetCertificate);
Run Code Online (Sandbox Code Playgroud)

在示例中,还禁用了吊销检查,但如果您对CRL具有在线或离线访问权限,则可以启用它.


所述ExtraStore应该允许包括中间证书不在设备/用户存储.但是,受信任的根证书可能需要位于计算机或用户存储中,具体取决于指定的证书,X509Chain否则您将收到UntrustedRoot失败.如果甚至根目录在计算机或用户存储中都不可用,那么您可以尝试走向生成的链并保证您唯一的错误是由于不可信的根,同时保证链根是你的会根据X509Certificate2Collection您的验证情况来预期.

或者,您可以创建自己的自定义X509CertificateValidator来验证证书,仅考虑提供的证书X509Certificate2Collection.