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

Man*_*dey 5 .net c# saml single-sign-on

嗨,我是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>
Run Code Online (Sandbox Code Playgroud)

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

han*_*anz 4

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

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

我还指定了我想在 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);

    }
Run Code Online (Sandbox Code Playgroud)

一旦断言被加密......这就是它的样子:

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

    }
Run Code Online (Sandbox Code Playgroud)

  • `AddPrefix` 有什么作用? (2认同)