Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create SAML 2.0 response with signed and encrypted Assertion using c#

Hi I am new to SAML and SSO techniques. I am trying to create a valid SAML reponse with signed and encrypted Assertion. I have created a SAML response which is signed but i am not able to encrypte the assertion and create the tag. My Generated SAML response is,

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

Can any one suggest any method to accomplish this?

like image 809
Manish Pandey Avatar asked Sep 28 '22 11:09

Manish Pandey


1 Answers

it depends what kind of encryption you want to use... Basically you would have to encrypt signed assertion and replace assertion node with EncryptedAssertion node.

I recommend using both symmetric and asymmetric encryption. Using Symmetric key to encrypt the whole of assertion node and then use asymmetric (i.e. certificate public/private key to encrypt symmetric key). I have used our client's certificate public key to encrypt symmetric key so only they can decrypt using their private key.

I have also specified certificate I want to use in 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);

    }

Once assertion is encrypted.. this is what it will look like:

<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>
like image 108
hanz Avatar answered Oct 03 '22 00:10

hanz