XML encryption and decryption for multiple recipients with X509 certificates XML encryption and decryption for multiple recipients with X509 certificates xml xml

XML encryption and decryption for multiple recipients with X509 certificates


The EncryptedElement class can take as many EncryptedKeys as you want. As long as the other party can correctly identify their EncryptedKey (using the Recipient or the KeyInfoName elements), you should not have any problems:

// example xmlXmlDocument 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 storeRSA rsaKey1 = new RSACryptoServiceProvider();RSA rsaKey2 = new RSACryptoServiceProvider();var publicKeys = new[] { rsaKey1, rsaKey2 };string sessKeyName = "helloworldkey";var sessKey = new RijndaelManaged() { KeySize = 256 };// encryptvar 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'sint 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 xmlEncryptedXml.ReplaceElement(elementToEncrypt, encryptedElement, false);// show the resultConsole.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>

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

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

Result:

<root><encryptme>hello world</encryptme></root>