11

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

所以我有一个.p7b文件来验证,它可以读入X509Certificate2Collection一个示例断言 - 一个 base 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

这很有效,但它所做的只是检查X509Certificate2SAML 响应中的签名和公钥是否匹配。它不会以任何方式验证它来自谁,我需要在接受 SAML 身份验证之前这样做。

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

然而,两者都返回假。

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

似乎没有任何方法可以将 传递X509Certificate2CollectionVerifyorCheckSignature方法。

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

有什么方法可以.p7b按照我想要的方式使用证书吗?

4

1 回答 1

7

您是否尝试过在验证过程中使用自定义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);

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


ExtraStore应该允许包含不在机器/用户存储中的中间证书。但是,受信任的根证书可能需要位于机器或用户存储中,具体取决于 中指定的证书,X509Chain否则您将UntrustedRoot失败。如果在机器或用户存储中连根都不可用,您可以尝试沿着生成的链向上走,并保证您遇到的唯一错误是由于不受信任的根,同时保证链根是您的期望基于X509Certificate2Collection您的验证。

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

于 2011-05-31T11:41:39.900 回答