使用c#创建带有签名和加密断言的SAML 2.0响应

时间:2015-03-26 13:39:01

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

您好我是SAML和SSO技术的新手。我正在尝试使用签名和加密的断言创建有效的SAML响应。我创建了一个签名的SAML响应,但我无法加密断言并创建标记。我生成的SAML响应是,

<samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_88a4cf19-6f41-46ee-9dc3-98ac80168bd9" Version="2.0" IssueInstant="2015-03-26T11:43:13.4468624Z" Destination="Test1" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml:Issuer>Test</saml:Issuer>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
            <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <Reference URI="#_49bc8835-7c9a-4ee2-8087-7cfcbe48375f">
                <Transforms>
                    <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                    <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <DigestValue>My4iQVO1Oy3i6jV+Jlp0czX0mpA=</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>GWfdKMCHbiqq6OhyHQ0y2LoDQkmC95fs3SKWyPMzu6jSjbf6vrMRFCrlch+DU1k3+sfsj1tFkJNMPKpxZIx2XksjnEQv3Hdqy7oPSoGiODmrky7CTKEdYbCQqu6a8dwNBLNQTClYAgDz/m5yfbFlJNPy9TtsCl2l1R/qg6dzVkA=</SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>MIIBwTCCAS6gAwIBAgIQr71oSHfrBKpKpRUTWmBFCzAJBgUrDgMCHQUAMCMxITAfBgNVBAMeGABCAEYASQBcAGQAcwBwAGUAaQBnAGgAdDAeFw0xMDAyMTkxMzI4MzlaFw0xMTAyMTkxOTI4MzlaMCMxITAfBgNVBAMeGABCAEYASQBcAGQAcwBwAGUAaQBnAGgAdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxXmIj8FBaL+94B/fNsBcoNZZraicGsm5+8VtWQIaGdM65q6vgDSQAg4zOkTQCqKh2vlN2NHSZb2XjcrUTWm2Vb279dvkOZfZ1mdQeLjM2LbXvrY4e7qK1dhZy9gZ3Mhvuk3cKPwwPsLNFifOt6OsS8ZzK7/PC+uUKznZtRsCAwEAATAJBgUrDgMCHQUAA4GBADGP1MjZm28GdYy3mQGprHQNDn8fIyBQvhwVwl4SVPxYDTKG7OsUC/QDUzy8vGXm+9qd2Es5creZS1DTAweC60JsJLdmp631FnbG4xJOCRHbR0HWyruhGkN6wPJ0RyJbdUrAcEPG4cfcYwl3oBeL48MfUD56UC0jSfBezUvnOMBX</X509Certificate>
            </X509Data>
        </KeyInfo>
    </Signature>
    <samlp:Status>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    </samlp:Status>
    <saml:Assertion Version="2.0" ID="_49bc8835-7c9a-4ee2-8087-7cfcbe48375f" IssueInstant="2015-03-26T11:43:13.6835615Z">
        <saml:Issuer>Test</saml:Issuer>
        <saml:Subject>
            <saml:NameID NameQualifier="TestDomain">TestSubject</saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData NotOnOrAfter="2015-03-26T11:48:13.7304370Z" Recipient="Test1" />
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions NotBefore="2015-03-26T11:43:13.6835615Z" NotOnOrAfter="2015-03-26T11:48:13.6835615Z">
            <saml:AudienceRestriction>
                <saml:Audience>TestDomain</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
        <saml:AuthnStatement AuthnInstant="2015-03-26T11:43:13.6835615Z">
            <saml:AuthnContext>
                <saml:AuthnContextClassRef>AuthnContextClassRef</saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>
        <saml:AttributeStatement>
            <saml:Attribute Name="UserId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
                <saml:AttributeValue xmlns:q1="http://www.w3.org/2001/XMLSchema" p7:type="q1:string" xmlns:p7="http://www.w3.org/2001/XMLSchema-instance">1000001</saml:AttributeValue>
            </saml:Attribute>
            <saml:Attribute Name="UserName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
                <saml:AttributeValue xmlns:q2="http://www.w3.org/2001/XMLSchema" p7:type="q2:string" xmlns:p7="http://www.w3.org/2001/XMLSchema-instance">Manish Pandey</saml:AttributeValue>
            </saml:Attribute>
        </saml:AttributeStatement>
    </saml:Assertion>
</samlp:Response>

任何人都可以建议任何方法来实现这个目标吗?

1 个答案:

答案 0 :(得分:3)

它取决于您要使用哪种加密...基本上您必须加密已签名的断言并用EncryptedAssertion节点替换断言节点。

我建议使用对称和非对称加密。 使用Symmetric密钥加密整个断言节点,然后使用非对称(即证书公钥/私钥加密对称密钥)。我使用客户端的证书公钥来加密对称密钥,因此只有他们可以使用他们的私钥解密。

我还指定了我想在web.config中使用的证书......

    string samlResponseXml = '<SAML Response Message>'

    XmlDocument loginResponseXmlDocument = new XmlDocument();
    loginResponseXmlDocument.LoadXml(samlResponseXml);

    // Add name spaces
        XmlNamespaceManager namespaceManager = new XmlNamespaceManager(loginResponseXmlDocument.NameTable);
        namespaceManager.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol");
        namespaceManager.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
        namespaceManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
        namespaceManager.AddNamespace("xenc", "http://www.w3.org/2001/04/xmlenc#");


    Encrypt(loginResponseXmlDocument, namespaceManager);


    private void Encrypt(XmlDocument document, XmlNamespaceManager namespaceManager)
    {
        // create symmetric key
        var key = new RijndaelManaged();
        key.BlockSize = 128;
        key.KeySize = 256;
        key.Padding = PaddingMode.ISO10126;
        key.Mode = CipherMode.CBC;

        XmlElement assertion = (XmlElement)document.SelectSingleNode("/samlp:Response/saml:Assertion", namespaceManager);

        EncryptedXml eXml = new EncryptedXml();

        byte[] encryptedElement = eXml.EncryptData(assertion, key, false);

        EncryptedData edElement = new EncryptedData
        {
            Type = EncryptedXml.XmlEncAES256Url
        };

        const string encryptionMethod = EncryptedXml.XmlEncAES256Url;
        edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);
        edElement.CipherData.CipherValue = encryptedElement;

        // edElement = EncryptedData 

        // Now encrypt symmetric key
        string certificateDn = ConfigurationManager.AppSettings["CertificateDN"];
        X509Certificate2 x509Certificate = GetCertificate(certificateDn);

        RSACryptoServiceProvider rsa = x509Certificate.PublicKey.Key as RSACryptoServiceProvider;
        byte[] cryptedData = rsa.Encrypt(key.Key, false);
        //string data = Convert.ToBase64String(cryptedData);

        //byte[] encryptedKey = EncryptedXml.EncryptKey(key.Key, rsa, true);



        EncryptedKey ek = new EncryptedKey();
        ek.CipherData = new CipherData(cryptedData);
        ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);

        //EncryptedData edkey = new EncryptedData(); 
        //string data1 = Convert.ToBase64String(encryptedKey);
        //edkey.CipherData.CipherValue = System.Text.Encoding.Unicode.GetBytes(data);

        rsa.Clear();

        XmlDocument encryptedAssertion = new XmlDocument();

        // Add name spaces
        XmlDeclaration xmlDeclaration = encryptedAssertion.CreateXmlDeclaration("1.0", "UTF-8", null);
        XmlElement encryptedRoot = encryptedAssertion.DocumentElement;
        encryptedAssertion.InsertBefore(xmlDeclaration, encryptedRoot);

        XmlElement encryptedAssertionElement = encryptedAssertion.CreateElement("saml", "EncryptedAssertion", "urn:oasis:names:tc:SAML:2.0:assertion");
        encryptedAssertion.AppendChild(encryptedAssertionElement);


        string xml = edElement.GetXml().OuterXml;
        XmlElement element = AddPrefix(xml, "xenc", "http://www.w3.org/2001/04/xmlenc#");
        var encryptedDataNode = encryptedAssertion.ImportNode(element, true);
        encryptedAssertionElement.AppendChild(encryptedDataNode);


        xml = ek.GetXml().OuterXml;
        element = AddPrefix(xml, "xenc", "http://www.w3.org/2001/04/xmlenc#");
        var encryptedKeyNode = encryptedAssertion.ImportNode(element, true);
        encryptedAssertionElement.AppendChild(encryptedKeyNode);


        var root = document.DocumentElement;
        var node = root.OwnerDocument.ImportNode(encryptedAssertionElement, true);
        root.RemoveChild(assertion);
        root.AppendChild(node);

    }

断言加密后......这就是它的样子:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
        xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Destination="https://aviva-rpt.distribution-technology.com" ID="_fba2f5af-a430-8001-5cb8-9714f3aeb4bc" 
IssueInstant="2015-02-04T16:32:33.446Z" Version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
	<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://www.client.sds</saml:Issuer>
	<samlp:Status>
		<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
	</samlp:Status>
	<saml:EncryptedAssertion>
		<xenc:EncryptedData>
			<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
			<xenc:CipherData>
				<xenc:CipherValue>zjAgkZ=</xenc:CipherValue>
			</xenc:CipherData>
		</xenc:EncryptedData>
		<xenc:EncryptedKey>
			<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
			<xenc:CipherData>
				<xenc:CipherValue>DyA22==</xenc:CipherValue>
			</xenc:CipherData>
		</xenc:EncryptedKey>
	</saml:EncryptedAssertion>
</samlp:Response>