C# SAML RSA FIM(EMC)无法验证签名

C# SAML RSA FIM(EMC)无法验证签名,c#,.net,single-sign-on,saml-2.0,C#,.net,Single Sign On,Saml 2.0,我作为服务提供商实施SSO,ID提供商是RSA FIM,又称EMC。我成功地向他们发送了一个AuthN请求并收到了一个saml响应,但我似乎只是验证了签名。他们已经向我发送了他们实际的.cer文件,目前我直接将其拉出来并获取公钥。然后将其传递给check签名函数。任何帮助或指点将不胜感激,并让我知道如果任何澄清是必要的。我没有得到任何错误,只是每次都在检查签名方法上出错,不管发生什么。我已经尝试将编码从utf-8更改为ASCII。毫无用处,似乎什么都不管用,我快发疯了!哈哈 这就是逻辑: /*G

我作为服务提供商实施SSO,ID提供商是RSA FIM,又称EMC。我成功地向他们发送了一个AuthN请求并收到了一个saml响应,但我似乎只是验证了签名。他们已经向我发送了他们实际的.cer文件,目前我直接将其拉出来并获取公钥。然后将其传递给check签名函数。任何帮助或指点将不胜感激,并让我知道如果任何澄清是必要的。我没有得到任何错误,只是每次都在检查签名方法上出错,不管发生什么。我已经尝试将编码从utf-8更改为ASCII。毫无用处,似乎什么都不管用,我快发疯了!哈哈

这就是逻辑:

/*Get XML in previous function and build saml doc.*/

byte[] base64EncodedBytes = Convert.FromBase64String(samlResponse);
samlXml = System.Text.Encoding.UTF8.GetString(base64EncodedBytes); 

_SamlDocument = new XmlDocument();
_SamlDocument.PreserveWhitespace = true;
_SamlDocument.LoadXml(samlXml);


/*Verify Function*/
        public Boolean Verify()
        {
            // Check arguments.
            if (_SamlDocument == null)
                throw new ArgumentException("Invalid XML Doc.");

            // Create a new SignedXml object and pass it
            // the XML document class.
            SamlSignedXml signedXml = new SamlSignedXml(_SamlDocument, "ID");

            XmlNamespaceManager manager = new XmlNamespaceManager(_SamlDocument.NameTable);
            manager.AddNamespace("ds", SamlSignedXml.XmlDsigNamespaceUrl);

            // Find the "Signature" node and create a new
            // XmlNodeList object.
            XmlNodeList nodeList =  _SamlDocument.SelectNodes("//ds:Signature", manager);

            // Throw an exception if no signature was found.
            if (nodeList.Count <= 0)
            {
                throw new CryptographicException("Verification failed: No Signature was found in the document.");
            }

            // This example only supports one signature for
            // the entire XML document.  Throw an exception
            // if more than one signature was found.
            if (nodeList.Count >= 2)
            {
                throw new CryptographicException("Verification failed: More that one signature was found for the document.");
            }

            // Load the first <signature> node.
            signedXml.LoadXml((XmlElement)nodeList[0]);

            var bVerified = false;

            /*Pulls in .cer file directly from brand cert string which is a file location.*/
            X509Certificate2 brandCert = new X509Certificate2(brandCertificateString);
            bVerified = signedXml.CheckSignature(brandCert.PublicKey.Key);

            return bVerified;
        }
/*在前面的函数中获取XML并构建saml文档*/
字节[]base64EncodedBytes=Convert.FromBase64String(samlResponse);
samlXml=System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
_SamlDocument=newxmldocument();
_SamlDocument.PreserveWhitespace=true;
_LoadXml(samlXml);
/*验证功能*/
公共布尔验证()
{
//检查参数。
如果(_SamlDocument==null)
抛出新ArgumentException(“无效的XML文档”);
//创建一个新的SignedXml对象并传递它
//XML文档类。
SamlSignedXml signedXml=新的SamlSignedXml(_SamlDocument,“ID”);
XmlNamespaceManager=newxmlnamespacemanager(_SamlDocument.NameTable);
manager.AddNamespace(“ds”,SamlSignedXml.XmlDsigNamespaceUrl);
//找到“签名”节点并创建一个新的
//XmlNodeList对象。
XmlNodeList nodeList=\u SamlDocument.SelectNodes(“//ds:Signature”,manager);
//如果未找到签名,则引发异常。
如果(nodeList.Count=2)
{
抛出新的加密异常(“验证失败:为文档找到了多个签名。”);
}
//加载第一个节点。
signedXml.LoadXml((xmlement)节点列表[0]);
var bVerified=假;
/*直接从作为文件位置的品牌证书字符串中拉入.cer文件*/
X509Certificate2 brandCert=新X509Certificate2(brandCertificateString);
bVerified=signedXml.CheckSignature(brandCert.PublicKey.Key);
返回验证;
}
/发送的saml响应示例/

\u删除的信息_
Bi9EXd/yvWKHV7Hvc8tB3ddmDW8=
eCwiyItypMUOW9dUs8nEx5ufKRZfwCcDKTvkEYa4UQA048N9Sno4/tPJICenhV/5SCjnMSR4wx5q
FKcS5FiMK0q1JFl3qeDzUwl1zH1kqJQjS1fUatC7SKvCRRAI25nNapGT/4DZiaTmEt3tzf/o36b0
HHYULKFI3RLAETZJ91VE7UH5DOI6GPAAG9P8RTBDxVNHSGNUYIAJOG8MUUXUD3WAUDNAHMVUBSQ
RJSR0GW4X92K60LBMCU+qHNtpZyT96LyKVW5MF9HklQOkEW0ip8AJD3u6n3RTAtQnmoIJIOzSzH
15PNMOJVWZD7UQNWJAZIJWR7NYIDBSPggytva==
_removedinformation\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu_
谢谢,
马克

多亏基思的《从这里来》我才找到了答案()。使用名称管理器深入到签名节点非常有效,为我提供了一个干净的签名验证。我不得不稍微修改,以便从响应节点而不是断言节点提取签名,但它工作得很好。非常感谢你,基思

// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml("The SAML XML that you were sent");

// 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("asrt", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("dsig", @"http://www.w3.org/2000/09/xmldsig#");

// get nodes down to the signature
var responseNode = assertion.SelectSingleNode("/samlp:Response", ns);
var assertionNode = responseNode.SelectSingleNode("asrt:Assertion", ns);
var signNode = assertionNode.SelectSingleNode("dsig:Signature", ns);

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

// get the certificate, basically:
//     signedXml.KeyInfo[0].Certificates[0]
// ...but with added casting
var certificate = GetFirstX509Certificate(signedXml);

// check the key and signature match
bool isSigned = signedXml.CheckSignature(certificate, true);
// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml("The SAML XML that you were sent");

// 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("asrt", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("dsig", @"http://www.w3.org/2000/09/xmldsig#");

// get nodes down to the signature
var responseNode = assertion.SelectSingleNode("/samlp:Response", ns);
var assertionNode = responseNode.SelectSingleNode("asrt:Assertion", ns);
var signNode = assertionNode.SelectSingleNode("dsig:Signature", ns);

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

// get the certificate, basically:
//     signedXml.KeyInfo[0].Certificates[0]
// ...but with added casting
var certificate = GetFirstX509Certificate(signedXml);

// check the key and signature match
bool isSigned = signedXml.CheckSignature(certificate, true);