How to: Decrypt XML Elements with Symmetric Keys

You can use the classes in the System.Security.Cryptography.Xml namespace to encrypt an element within an XML document. XML Encryption allows you to store or transport sensitive XML, without worrying about the data being easily read. This code example decrypts an XML element using the Advanced Encryption Standard (AES) algorithm, also known as Rijndael.

For information about how to encrypt an XML element using this procedure, see How to: Encrypt XML Elements with Symmetric Keys.

When you use a symmetric algorithm like AES to encrypt XML data, you must use the same key to encrypt and decrypt the XML data. The example in this procedure assumes that the encrypted XML was encrypted using the same key, and that the encrypting and decrypting parties agree on the algorithm and key to use. This example does not store or encrypt the AES key within the encrypted XML.

This example is appropriate for situations where a single application needs to encrypt data based on a session key stored in memory, or based on a cryptographically strong key derived from a password. For situations where two or more applications need to share encrypted XML data, consider using an encryption scheme based on an asymmetric algorithm or an X.509 certificate.

To decrypt an XML element with a symmetric key

  1. Encrypt an XML element with the previously generated key using the techniques described in How to: Encrypt XML Elements with Symmetric Keys.

  2. Find the <EncryptedData> element (defined by the XML Encryption standard) in an XmlDocument object that contains the encrypted XML and create a new XmlElement object to represent that element.

    Dim encryptedElement As XmlElement = Doc.GetElementsByTagName("EncryptedData")(0)
    
             XmlElement encryptedElement = Doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;
    
  3. Create an EncryptedData object by loading the raw XML data from the previously created XmlElement object.

    Dim edElement As New EncryptedData()
    edElement.LoadXml(encryptedElement)
    
              EncryptedData edElement = new EncryptedData();
                edElement.LoadXml(encryptedElement);
    
  4. Create a new EncryptedXml object and use it to decrypt the XML data using the same key that was used for encryption.

    Dim exml As New EncryptedXml()
    
    
    ' Decrypt the element using the symmetric key. 
    Dim rgbOutput As Byte() = exml.DecryptData(edElement, Alg)
    
               EncryptedXml exml = new EncryptedXml();
    
    
                // Decrypt the element using the symmetric key. 
                byte[] rgbOutput = exml.DecryptData(edElement, Alg);
    
  5. Replace the encrypted element with the newly decrypted plaintext element within the XML document.

    exml.ReplaceData(encryptedElement, rgbOutput)
    
             exml.ReplaceData(encryptedElement, rgbOutput);
    

Example

This example assumes that a file named "test.xml" exists in the same directory as the compiled program. It also assumes that "test.xml" contains a "creditcard" element. You can place the following XML into a file called test.xml and use it with this example.

<root>
    <creditcard>
        <number>19834209</number>
        <expiry>02/02/2002</expiry>
    </creditcard>
</root>
Imports System
Imports System.Xml
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml




Module Program

    Sub Main(ByVal args() As String)
        Dim key As RijndaelManaged = Nothing 

        Try 
            ' Create a new Rijndael key.
            key = New RijndaelManaged()
            ' Load an XML document. 
            Dim xmlDoc As New XmlDocument()
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load("test.xml")
            ' Encrypt the "creditcard" element.
            Encrypt(xmlDoc, "creditcard", key)

            Console.WriteLine("The element was encrypted")

            Console.WriteLine(xmlDoc.InnerXml)

            Decrypt(xmlDoc, key)

            Console.WriteLine("The element was decrypted")

            Console.WriteLine(xmlDoc.InnerXml)


        Catch e As Exception
            Console.WriteLine(e.Message)
        Finally 
            ' Clear the key. 
            If Not (key Is Nothing) Then
                key.Clear()
            End If 
        End Try 

    End Sub 


    Sub Encrypt(ByVal Doc As XmlDocument, ByVal ElementName As String, ByVal Key As SymmetricAlgorithm)
        ' Check the arguments.   
        If Doc Is Nothing Then 
            Throw New ArgumentNullException("Doc")
        End If 
        If ElementName Is Nothing Then 
            Throw New ArgumentNullException("ElementToEncrypt")
        End If 
        If Key Is Nothing Then 
            Throw New ArgumentNullException("Alg")
        End If 
        '''''''''''''''''''''''''''''''''''''''''''''''''' 
        ' Find the specified element in the XmlDocument 
        ' object and create a new XmlElemnt object. 
        '''''''''''''''''''''''''''''''''''''''''''''''''' 
        Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementName)(0)

        ' Throw an XmlException if the element was not found. 
        If elementToEncrypt Is Nothing Then 
            Throw New XmlException("The specified element was not found")
        End If 

        '''''''''''''''''''''''''''''''''''''''''''''''''' 
        ' Create a new instance of the EncryptedXml class  
        ' and use it to encrypt the XmlElement with the  
        ' symmetric key. 
        '''''''''''''''''''''''''''''''''''''''''''''''''' 
        Dim eXml As New EncryptedXml()

        Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, Key, False)
        '''''''''''''''''''''''''''''''''''''''''''''''''' 
        ' Construct an EncryptedData object and populate 
        ' it with the desired encryption information. 
        '''''''''''''''''''''''''''''''''''''''''''''''''' 
        Dim edElement As New EncryptedData()
        edElement.Type = EncryptedXml.XmlEncElementUrl
        ' Create an EncryptionMethod element so that the  
        ' receiver knows which algorithm to use for decryption. 
        ' Determine what kind of algorithm is being used and 
        ' supply the appropriate URL to the EncryptionMethod element. 
        Dim encryptionMethod As String = Nothing 

        If TypeOf Key Is TripleDES Then
            encryptionMethod = EncryptedXml.XmlEncTripleDESUrl
        ElseIf TypeOf Key Is DES Then
            encryptionMethod = EncryptedXml.XmlEncDESUrl
        End If 
        If TypeOf Key Is Rijndael Then 
            Select Case Key.KeySize
                Case 128
                    encryptionMethod = EncryptedXml.XmlEncAES128Url
                Case 192
                    encryptionMethod = EncryptedXml.XmlEncAES192Url
                Case 256
                    encryptionMethod = EncryptedXml.XmlEncAES256Url
            End Select 
        Else 
            ' Throw an exception if the transform is not in the previous categories 
            Throw New CryptographicException("The specified algorithm is not supported for XML Encryption.")
        End If

        edElement.EncryptionMethod = New EncryptionMethod(encryptionMethod)
        ' Add the encrypted element data to the  
        ' EncryptedData object.
        edElement.CipherData.CipherValue = encryptedElement
        '''''''''''''''''''''''''''''''''''''''''''''''''' 
        ' Replace the element from the original XmlDocument 
        ' object with the EncryptedData element. 
        ''''''''''''''''''''''''''''''''''''''''''''''''''
        EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)

    End Sub 'Encrypt


    Sub Decrypt(ByVal Doc As XmlDocument, ByVal Alg As SymmetricAlgorithm)
        ' Check the arguments.   
        If Doc Is Nothing Then 
            Throw New ArgumentNullException("Doc")
        End If 
        If Alg Is Nothing Then 
            Throw New ArgumentNullException("Alg")
        End If 
        ' Find the EncryptedData element in the XmlDocument. 
        Dim encryptedElement As XmlElement = Doc.GetElementsByTagName("EncryptedData")(0)

        ' If the EncryptedData element was not found, throw an exception. 
        If encryptedElement Is Nothing Then 
            Throw New XmlException("The EncryptedData element was not found.")
        End If 


        ' Create an EncryptedData object and populate it. 
        Dim edElement As New EncryptedData()
        edElement.LoadXml(encryptedElement)
        ' Create a new EncryptedXml object. 
        Dim exml As New EncryptedXml()


        ' Decrypt the element using the symmetric key. 
        Dim rgbOutput As Byte() = exml.DecryptData(edElement, Alg)
        ' Replace the encryptedData element with the plaintext XML element.
        exml.ReplaceData(encryptedElement, rgbOutput)
    End Sub 
End Module
using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;


namespace CSCrypto
{
    class Program
    {
        static void Main(string[] args)
        {
            RijndaelManaged key = null;

            try
            {
                // Create a new Rijndael key.
                key = new RijndaelManaged();
                // Load an XML document.
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.PreserveWhitespace = true;
                xmlDoc.Load("test.xml");

                // Encrypt the "creditcard" element.
                Encrypt(xmlDoc, "creditcard", key);

                Console.WriteLine("The element was encrypted");

                Console.WriteLine(xmlDoc.InnerXml);

                Decrypt(xmlDoc, key);

                Console.WriteLine("The element was decrypted");

                Console.WriteLine(xmlDoc.InnerXml);

                
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                // Clear the key. 
                if (key != null)
                {
                    key.Clear();
                }
            }

        }

        public static void Encrypt(XmlDocument Doc, string ElementName, SymmetricAlgorithm Key)
        {
            // Check the arguments.   
            if (Doc == null)
                throw new ArgumentNullException("Doc");
            if (ElementName == null)
                throw new ArgumentNullException("ElementToEncrypt");
            if (Key == null)
                throw new ArgumentNullException("Alg");

            //////////////////////////////////////////////// 
            // Find the specified element in the XmlDocument 
            // object and create a new XmlElemnt object. 
            ////////////////////////////////////////////////
            XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementName)[0] as XmlElement;
            // Throw an XmlException if the element was not found. 
            if (elementToEncrypt == null)
            {
                throw new XmlException("The specified element was not found");

            }

            ////////////////////////////////////////////////// 
            // Create a new instance of the EncryptedXml class  
            // and use it to encrypt the XmlElement with the  
            // symmetric key. 
            //////////////////////////////////////////////////

            EncryptedXml eXml = new EncryptedXml();

            byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, Key, false);
            //////////////////////////////////////////////// 
            // Construct an EncryptedData object and populate 
            // it with the desired encryption information. 
            ////////////////////////////////////////////////

            EncryptedData edElement = new EncryptedData();
            edElement.Type = EncryptedXml.XmlEncElementUrl;

            // Create an EncryptionMethod element so that the  
            // receiver knows which algorithm to use for decryption. 
            // Determine what kind of algorithm is being used and 
            // supply the appropriate URL to the EncryptionMethod element. 

            string encryptionMethod = null;

            if (Key is TripleDES)
            {
                encryptionMethod = EncryptedXml.XmlEncTripleDESUrl;
            }
            else if (Key is DES)
            {
                encryptionMethod = EncryptedXml.XmlEncDESUrl;
            }
            if (Key is Rijndael)
            {
                switch (Key.KeySize)
                {
                    case 128:
                        encryptionMethod = EncryptedXml.XmlEncAES128Url;
                        break;
                    case 192:
                        encryptionMethod = EncryptedXml.XmlEncAES192Url;
                        break;
                    case 256:
                        encryptionMethod = EncryptedXml.XmlEncAES256Url;
                        break;
                }
            }
            else
            {
                // Throw an exception if the transform is not in the previous categories 
                throw new CryptographicException("The specified algorithm is not supported for XML Encryption.");
            }

            edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);

            // Add the encrypted element data to the  
            // EncryptedData object.
            edElement.CipherData.CipherValue = encryptedElement;

            //////////////////////////////////////////////////// 
            // Replace the element from the original XmlDocument 
            // object with the EncryptedData element. 
            ////////////////////////////////////////////////////
            EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
        }

        public static void Decrypt(XmlDocument Doc, SymmetricAlgorithm Alg)
        {
            // Check the arguments.   
            if (Doc == null)
                throw new ArgumentNullException("Doc");
            if (Alg == null)
                throw new ArgumentNullException("Alg");

            // Find the EncryptedData element in the XmlDocument.
            XmlElement encryptedElement = Doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;

            // If the EncryptedData element was not found, throw an exception. 
            if (encryptedElement == null)
            {
                throw new XmlException("The EncryptedData element was not found.");
            }

            
            // Create an EncryptedData object and populate it.
            EncryptedData edElement = new EncryptedData();
            edElement.LoadXml(encryptedElement);

            // Create a new EncryptedXml object.
            EncryptedXml exml = new EncryptedXml();
            

            // Decrypt the element using the symmetric key. 
            byte[] rgbOutput = exml.DecryptData(edElement, Alg);

            // Replace the encryptedData element with the plaintext XML element.
            exml.ReplaceData(encryptedElement, rgbOutput);

        }

    }


}
<root>
    <creditcard>
        <number>19834209</number>
        <expiry>02/02/2002</expiry>
    </creditcard>
</root>

Compiling the Code

Security

Never store a cryptographic key in plaintext or transfer a key between machines in plaintext.

When you are done using a symmetric cryptographic key, clear it from memory by setting each byte to zero or by calling the Clear method of the managed cryptography class.

See Also

Tasks

How to: Encrypt XML Elements with Symmetric Keys

Reference

System.Security.Cryptography.Xml

Other Resources

XML Encryption and Digital Signatures