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

时间:2013-05-28 15:36:56

标签: c# .net single-sign-on saml-2.0

我正在实施SSO作为服务提供商,ID提供商是RSA FIM aka EMC。我成功地向他们发送了一个AuthN请求并收到了一个saml响应,但我似乎可以验证签名。他们向我发送了他们的实际.cer文件,目前我直接将其拉出来并获取公钥。然后将其传递给检查签名功能。任何帮助或指示将不胜感激,如果需要澄清,请告诉我。每次无论如何,我都没有在检查签名方法上得到任何错误。我已经尝试将编码从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;
        }

/ 发送的样本saml响应。 /

<samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" Destination="_removed information_" ID="c9c96cd8c3e6cdef4d5c1d976968d347" InResponseTo="_5990ada8-e69f-4e66-90f1-d7e96dafbe4f" IssueInstant="2013-05-23T18:52:24Z" Version="2.0"><saml:Issuer>_removed information_</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
<ds:Reference URI="#c9c96cd8c3e6cdef4d5c1d976968d347">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>Bi9EXd/yvWKHV7Hvc8tB3ddmDW8=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
eCwiyItypMUOW9dUs8nEx5ufKRZfwCcDKTvkEYa4UQA048N9Sno4/tPJICenhV/5SCjnMSR4wx5q
FKcS5FiMK0q1JFl3qeDzUwl1zH1kqJQjS1fUatC7SKvCRRAI25nNapGT/4DZiaTmEt3tzf/o36b0
HHyuLkFI3RlaEtzJ91vE7uH5dOI6GPAaG9p8rtBDXvNWhsGnuYIaJog8MUUXuD3wAudNAhMvuBsq
rjsR0GW4x92k60lbMcus+qHNtpZyT96LyKVW5MF9HklQOkEW0ip8AJD3u6n3RTAtQnmoIJIOzSzH
15pnmOJJVWzD7UqnWjAZIjWR7NYiDBSpggYtvA==
</ds:SignatureValue>
</ds:Signature><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"></samlp:StatusCode></samlp:Status><saml:Assertion ID="d26d141cea5a9a5c912916a534957e04" IssueInstant="2013-05-23T18:52:24Z" Version="2.0"><saml:Issuer>_removedinformation_</saml:Issuer><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">_removed information_</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData InResponseTo="_5990ada8-e69f-4e66-90f1-d7e96dafbe4f" NotOnOrAfter="2013-05-23T18:53:24Z" Recipient="_removed information_"></saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2013-05-23T18:51:54Z" NotOnOrAfter="2013-05-23T18:53:24Z"><saml:AudienceRestriction><saml:Audience>_removed information_</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2013-05-23T18:52:23Z" SessionIndex="d26d141cea5a9a5c912916a534957e04"><saml:SubjectLocality Address="10.96.40.30" DNSName="localhost.localdomain"></saml:SubjectLocality><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><saml:Attribute FriendlyName="UserName" Name="UserName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue xsi:type="xs:string">_removed information_</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>

谢谢, 标记

1 个答案:

答案 0 :(得分:0)

我感谢基思来自这里(https://stackoverflow.com/a/6139044/778401)。使用名称管理器来完成签名节点的工作非常完美,并为我提供了一个干净的签名验证。我不得不稍微修改,以便从响应节点而不是断言节点拉出签名,但它工作得很漂亮。非常感谢基思!

// 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);