XML encryption and decryption for multiple recipients with X509 certificates

I was able to encrypt and decrypt XML documents using examples on MSDN. http://msdn.microsoft.com/en-us/library/ms229744.aspx and http://msdn.microsoft.com/en-us/library/ms229943.aspx

All this is done in accordance with the XML encryption standard W3C (XML Enc).

Everything works well. My problem is that one XML document is for 2 or 3 recipients. I want to encrypt the same xml with multiple keys (X509 certificate public key) so that the document can be decrypted by multiple recipients.

This is all possible according to the W3C XML encryption standard using several EncryptionKey elements that contain an encrypted symmetric session key.

I could not find any example of how to achieve this in .Net using standard cryptography classes.

This should be implemented in .NET C #.

Is there any way to do this or sample code somewhere?

+7
c # xml certificate encryption
source share
1 answer

The EncryptedElement class can accept as many EncryptedKeys as possible. While the other side can correctly identify their EncryptedKey (using the Recipient or KeyInfoName elements), you should not have any problems:

// example xml XmlDocument xdoc = new XmlDocument(); xdoc.PreserveWhitespace = true; xdoc.LoadXml(@"<root><encryptme>hello world</encryptme></root>"); var elementToEncrypt = (XmlElement)xdoc.GetElementsByTagName("encryptme")[0]; // keys // rsa keys would normally be pulled from a store RSA rsaKey1 = new RSACryptoServiceProvider(); RSA rsaKey2 = new RSACryptoServiceProvider(); var publicKeys = new[] { rsaKey1, rsaKey2 }; string sessKeyName = "helloworldkey"; var sessKey = new RijndaelManaged() { KeySize = 256 }; // encrypt var encXml = new EncryptedXml(); var encryptedElement = new EncryptedData() { Type = EncryptedXml.XmlEncElementUrl, EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url), KeyInfo = new KeyInfo() }; encryptedElement.CipherData.CipherValue = encXml.EncryptData(elementToEncrypt, sessKey, false); encryptedElement.KeyInfo.AddClause(new KeyInfoName(sessKeyName)); // encrypt the session key and add keyinfo's int keyID = 0; foreach (var pk in publicKeys) { var encKey = new EncryptedKey() { CipherData = new CipherData(EncryptedXml.EncryptKey(sessKey.Key, pk, false)), EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url), Recipient = string.Format("recipient{0}@foobar.com", ++keyID), CarriedKeyName = sessKeyName, }; encKey.KeyInfo.AddClause(new KeyInfoName(encKey.Recipient)); encryptedElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(encKey)); } // update the xml EncryptedXml.ReplaceElement(elementToEncrypt, encryptedElement, false); // show the result Console.Write(xdoc.InnerXml); Console.ReadLine(); Console.WriteLine(new string('-', 80)); 

Produces

 <root> <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName>helloworldkey</KeyName> <EncryptedKey Recipient=" recipient1@foobar.com " xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName> recipient1@foobar.com </KeyName> </KeyInfo> <CipherData> <CipherValue>bmVT4SuAgWto6NJoTnUhrwaQ5/bWx39WKfs8y/QEQbaEBqdvl2Wa3woQGZxfigZ2wsWZQJFW0YGMII0W6AATnsqGOOVEbdGxmnvXRISiRdhcyNHkHot0kDK987y446ws5CZQQuz8inGq/SNrhiK6RyVnBE4ykWjrJyIS5wScwqA=</CipherValue> </CipherData> <CarriedKeyName>helloworldkey</CarriedKeyName> </EncryptedKey> <EncryptedKey Recipient=" recipient2@foobar.com " xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName> recipient2@foobar.com </KeyName> </KeyInfo> <CipherData> <CipherValue>oR8NPTm1NasWeDXBjayLk+p9/5RTWOZwNJHUMTQpZB9v1Aasi75oSjGqSqN0HMTiviw6NWz8AvHB9+i08L4Hw8JRDLxZgjaKqTGu31wXmM3Vc0CoYQ15AWMZN4q4tSxDhwuT8fp9SN+WFBm+M3w3bcPoooAazzDHK3ErzfXzYiU=</CipherValue> </CipherData> <CarriedKeyName>helloworldkey</CarriedKeyName> </EncryptedKey> </KeyInfo> <CipherData> <CipherValue>ohjWIEFf2WO6v/CC+ugd7uxEKGJlxgdT9N+t3MhoTIyXHqT5VlknWs0XlAhcgajkxKFjwVO3p413eRSMTLXKCg==</CipherValue> </CipherData> </EncryptedData> </root> / SNrhiK6RyVnBE4ykWjrJyIS5wScwqA = </ CipherValue> <root> <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName>helloworldkey</KeyName> <EncryptedKey Recipient=" recipient1@foobar.com " xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName> recipient1@foobar.com </KeyName> </KeyInfo> <CipherData> <CipherValue>bmVT4SuAgWto6NJoTnUhrwaQ5/bWx39WKfs8y/QEQbaEBqdvl2Wa3woQGZxfigZ2wsWZQJFW0YGMII0W6AATnsqGOOVEbdGxmnvXRISiRdhcyNHkHot0kDK987y446ws5CZQQuz8inGq/SNrhiK6RyVnBE4ykWjrJyIS5wScwqA=</CipherValue> </CipherData> <CarriedKeyName>helloworldkey</CarriedKeyName> </EncryptedKey> <EncryptedKey Recipient=" recipient2@foobar.com " xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName> recipient2@foobar.com </KeyName> </KeyInfo> <CipherData> <CipherValue>oR8NPTm1NasWeDXBjayLk+p9/5RTWOZwNJHUMTQpZB9v1Aasi75oSjGqSqN0HMTiviw6NWz8AvHB9+i08L4Hw8JRDLxZgjaKqTGu31wXmM3Vc0CoYQ15AWMZN4q4tSxDhwuT8fp9SN+WFBm+M3w3bcPoooAazzDHK3ErzfXzYiU=</CipherValue> </CipherData> <CarriedKeyName>helloworldkey</CarriedKeyName> </EncryptedKey> </KeyInfo> <CipherData> <CipherValue>ohjWIEFf2WO6v/CC+ugd7uxEKGJlxgdT9N+t3MhoTIyXHqT5VlknWs0XlAhcgajkxKFjwVO3p413eRSMTLXKCg==</CipherValue> </CipherData> </EncryptedData> </root> + i08L4Hw8JRDLxZgjaKqTGu31wXmM3Vc0CoYQ15AWMZN4q4tSxDhwuT8fp9SN + WFBm + M3w3bcPoooAazzDHK3ErzfXzYiU = </ CipherValue> <root> <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName>helloworldkey</KeyName> <EncryptedKey Recipient=" recipient1@foobar.com " xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName> recipient1@foobar.com </KeyName> </KeyInfo> <CipherData> <CipherValue>bmVT4SuAgWto6NJoTnUhrwaQ5/bWx39WKfs8y/QEQbaEBqdvl2Wa3woQGZxfigZ2wsWZQJFW0YGMII0W6AATnsqGOOVEbdGxmnvXRISiRdhcyNHkHot0kDK987y446ws5CZQQuz8inGq/SNrhiK6RyVnBE4ykWjrJyIS5wScwqA=</CipherValue> </CipherData> <CarriedKeyName>helloworldkey</CarriedKeyName> </EncryptedKey> <EncryptedKey Recipient=" recipient2@foobar.com " xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName> recipient2@foobar.com </KeyName> </KeyInfo> <CipherData> <CipherValue>oR8NPTm1NasWeDXBjayLk+p9/5RTWOZwNJHUMTQpZB9v1Aasi75oSjGqSqN0HMTiviw6NWz8AvHB9+i08L4Hw8JRDLxZgjaKqTGu31wXmM3Vc0CoYQ15AWMZN4q4tSxDhwuT8fp9SN+WFBm+M3w3bcPoooAazzDHK3ErzfXzYiU=</CipherValue> </CipherData> <CarriedKeyName>helloworldkey</CarriedKeyName> </EncryptedKey> </KeyInfo> <CipherData> <CipherValue>ohjWIEFf2WO6v/CC+ugd7uxEKGJlxgdT9N+t3MhoTIyXHqT5VlknWs0XlAhcgajkxKFjwVO3p413eRSMTLXKCg==</CipherValue> </CipherData> </EncryptedData> </root> 

To decrypt a document, you must provide a mapping between the key name and the private key of the certificate:

 // Decrypt string myKeyName = " recipient1@foobar.com "; // specify we want to use the key for recipient1 var encryptedDoc = new EncryptedXml(xdoc); encryptedDoc.AddKeyNameMapping(myKeyName, rsaKey1); encryptedDoc.Recipient = myKeyName; // Decrypt the element. encryptedDoc.DecryptDocument(); // show the result Console.Write(xdoc.InnerXml); Console.ReadLine(); 

Result:

 <root><encryptme>hello world</encryptme></root> 
+4
source share

All Articles