我正在编写一个 SAML 2.0 响应解析器来处理 ASP.Net 中的 POST 身份验证(在 C# 和 MVC 中,但这不太相关)。
所以我有一个.p7b
要验证的文件并且可以读入X509Certificate2Collection
以及示例断言 - Base 64 编码的 SAML 响应。
理想情况下我想使用内置的WSSecurityTokenSerializer
, but 失败了 https://stackoverflow.com/questions/6108564,所以我正在寻找一种有效的方法。
我直接读取 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
这一切都有效,但它所做的只是检查签名和X509Certificate2
SAML 响应匹配中的公钥。它不会以任何方式验证它的来源,我需要在接受 SAML 身份验证之前执行此操作。
似乎有两种方法可以检查 SAML 响应中找到的证书 - 我可以这样做certificate.Verify()
或者我可以用签名进行检查signedXml.CheckSignature(certificate, false)
.
然而两者都返回 false。
我认为这是因为它们正在机器商店或可能在网上进行检查(我不知道如何检查)。我想检查它们X509Certificate2Collection
检索自.p7b
文件 - 在机器上注册的证书应该被忽略,而只是.p7b
证书已检查。
似乎没有任何方法可以通过X509Certificate2Collection
到任一Verify
or CheckSignature
方法。
这是对 SAML 响应进行的正确检查吗?
有什么办法可以使用.p7b
证书是我想要的方式吗?