如何根据 X509Certificate2Collection 链验证 X509Certificate2 [英] How to verify an X509Certificate2 against an X509Certificate2Collection chain
问题描述
我正在编写一个 SAML 2.0 响应解析器来处理 ASP.Net 中的 POST 身份验证(在 C# 和 MVC 中,但这不太相关).
I'm writing a SAML 2.0 response parser to handle POST authentication in ASP.Net (in C# and MVC, but that's less relevant).
所以我有一个 .p7b
文件来验证,它可以被读入一个 X509Certificate2Collection
和一个示例断言 - 一个 base 64 编码的 SAML 响应.
So I have a .p7b
file to validate with and that can be read into a X509Certificate2Collection
and a sample assertion - a base 64 encoded SAML response.
理想情况下,我想使用内置的 WSSecurityTokenSerializer
,但 失败,所以我寻找有效的方法.
Ideally I want to use the built in WSSecurityTokenSerializer
, but that fails, so I'm looking for a way that works.
我正在直接读取 XML:
I'm reading the XML directly instead:
// 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
这一切都有效,但它所做的只是检查 SAML 响应中的签名和 X509Certificate2
公钥是否匹配.它不会以任何方式验证它来自谁,我需要在接受 SAML 身份验证之前这样做.
That lot works, but all it's doing is checking that the signature and the X509Certificate2
public key in the SAML response match. It doesn't in any way verify who it's from, and I need to do that before accepting the SAML authentication.
似乎有两种方法可以检查在 SAML 响应中找到的证书 - 我可以执行 certificate.Verify()
或者我可以使用签名 signedXml.CheckSignature(证书,假)
.
There appear to be two ways to check the certificate found in the SAML response - I can do certificate.Verify()
or I can do the check with the signature signedXml.CheckSignature(certificate, false)
.
然而两者都返回 false.
However both return false.
我认为这是因为他们正在接受机器商店或可能在线的检查(我不确定如何检查).我想根据从 .p7b
文件中检索到的 X509Certificate2Collection
来检查它们 - 应该忽略在机器上注册的证书,而只是 .p7b
已检查证书.
I think this is because they're being checked against the machine store or possibly online (I'm not sure how to check). I want to check them against the X509Certificate2Collection
retrieved from the .p7b
file instead - the certificates registered on the machine should be ignored and just the .p7b
certificates checked.
似乎没有任何方法可以将 X509Certificate2Collection
传递给 Verify
或 CheckSignature
方法.
There doesn't appear to be any way to pass the X509Certificate2Collection
to either the Verify
or CheckSignature
methods.
这是对 SAML 响应进行的正确检查吗?
Is this the right check to be doing on the SAML response?
有没有办法按照我想要的方式使用 .p7b
证书?
Is there any way to use the .p7b
certificates the way I want to?
推荐答案
您是否尝试过使用自定义 X509Chain
配置来搜索 ExtraStore
验证过程中的证书.类似于以下内容:
Have you tried using a custom X509Chain
configured to search an ExtraStore
of certificates during the validation process. Something like the following:
// 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);
在示例中,撤销检查也被禁用,但如果您可以在线或离线访问 CRL,则可以启用它.
In the example the revocation check is also disabled but if you have online or offline access to the CRL you could enable it.
ExtraStore
应该允许包含不在机器/用户存储中的中间证书.但是,受信任的根证书可能需要位于机器或用户存储中,具体取决于 X509Chain
中指定的证书,否则您将获得 UntrustedRoot
失败.如果在机器或用户存储中连根都不可用,您可以尝试遍历结果链并保证您遇到的唯一错误是由于不受信任的根,同时保证链根是您的将期望基于 X509Certificate2Collection
用于验证.
The ExtraStore
should allow to include intermediate certificates that are not in the machine/user store. However, the trusted root certificate may need to be in the machine or user store depending on the one specified in X509Chain
because otherwise you'll get an UntrustedRoot
fail. If not even the root can be available in a machine or user store you could try to walk up the resulting chain and guarantee that the only error you have is due to an untrusted root and at the same time guaranteeing that the chain root is what you would expect based on the X509Certificate2Collection
you have for validation.
或者,您可以创建自己的自定义X509CertificateValidator
仅考虑提供的 X509Certificate2Collection
来验证证书.
Alternatively you could create your own custom X509CertificateValidator
to validate a certificate taking only in consideration a provided X509Certificate2Collection
.
这篇关于如何根据 X509Certificate2Collection 链验证 X509Certificate2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!