The scenario: the sender encrypts the xml using the AES symmetric algorithm and the key used by this algorithm is encrypted with the RSA public key of the receiver. Then when the receiver gets the document, uses its RSA private key to decrypt the AES key and with that key then decrypts the xml. All of this is made very easy by using the goodies from System.Security.Cryptography.Xml and the numerous MSDN examples.
However, there are no examples on how to get the AES key. This is done internal automatically when invoking DecryptDocument of the EncryptedXml class. Probably because most of the time you don’t care about that key.
But there are times when getting that key can be very useful, for example you can use that key to encrypt the response message and avoid this way the need for the original sender to have a RSA private/public set of keys also; or to add that password to a banned list of passwords in order not to accept another message encrypted with an already used password, etc.
/// <summary>
/// Gets the AES encryption key from a RSA+AES encrypted xml.
/// </summary>
/// <param name="xmlDoc">The xml document sent by the sender (encrypted).</param>
/// <param name="rsa">The RSACryptoServiceProvider (contains the private key of the receiver) wich will be used to decrypt the key with the name "keyName".</param>
/// <param name="keyName">The name of the key.</param>
/// <returns>The Aes key as a byte array.</returns>
public static byte[] GetAesKey(XmlDocument xmlDoc, RSACryptoServiceProvider rsa, string keyName)
{
//Treat the xmlDoc as encrypted xml.
EncryptedXml encryptedXml = new EncryptedXml(xmlDoc);
//link the name of the key we want to get to the algorithm used to decrypt
encryptedXml.AddKeyNameMapping(keyName, rsa);
//find the node encrypted
XmlNodeList encryptedElements = xmlDoc.GetElementsByTagName("EncryptedData");
if (encryptedElements.Count == 0)
return null;
XmlElement encryptedElement = (XmlElement)encryptedElements[0];
//load the encrypted node
EncryptedData eData = new EncryptedData();
eData.LoadXml(encryptedElement);
//finally gettting the key
SymmetricAlgorithm aes = encryptedXml.GetDecryptionKey(eData, eData.EncryptionMethod.KeyAlgorithm);
return aes.Key;
}
Note: There are some msdn examples about encrypting and decrypting with bugs - example here. If you use that code, when decrypting you’ll get Unable to retrieve the decryption key. This is because the encryption key never goes into the encrypted xml. The statement “edElement.KeyInfo = new KeyInfo();” from the Encrypt method overrides the key; move it before the previous statement or you just delete it (it is already initialized in the constructor).