如何根据 X509Certificate2Collection 链验证 X509Certificate2 [英] How to verify an X509Certificate2 against an X509Certificate2Collection chain

查看:94
本文介绍了如何根据 X509Certificate2Collection 链验证 X509Certificate2的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 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 传递给 VerifyCheckSignature 方法.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆