How to: Decrypt XML Elements with Asymmetric Keys
You can use the classes in the System.Security.Cryptography.Xml namespace to encrypt and decrypt an element within an XML document. XML Encryption is a standard way to exchange or store encrypted XML data, without worrying about the data being easily read. For more information about the XML Encryption standard, see the World Wide Web Consortium (W3C) recommendation XML Signature Syntax and Processing.
The example in this procedure decrypts an XML element that was encrypted using the methods described in How to: Encrypt XML Elements with Asymmetric Keys. It finds an <EncryptedData> element, decrypts the element, and then replaces the element with the original plaintext XML element.
This example decrypts an XML element using two keys. It retrieves a previously generated RSA private key from a key container, and then uses the RSA key to decrypt a session key stored in the <EncryptedKey> element of the <EncryptedData> element. The example then uses the session key to decrypt the XML element.
This example is appropriate for situations where multiple applications have to share encrypted data or where an application has to save encrypted data between the times that it runs.
To decrypt an XML element with an asymmetric key
Create a CspParameters object and specify the name of the key container.
Dim cspParams As New CspParameters() cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
Retrieve a previously generated asymmetric key from the container using the RSACryptoServiceProvider object. The key is automatically retrieved from the key container when you pass the CspParameters object to the RSACryptoServiceProvider constructor.
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
Create a new EncryptedXml object to decrypt the document.
' Create a new EncryptedXml object. Dim exml As New EncryptedXml(Doc)
// Create a new EncryptedXml object. EncryptedXml exml = new EncryptedXml(Doc);
Add a key/name mapping to associate the RSA key with the element within the document that should be decrypted. You must use the same name for the key that you used when you encrypted the document. Note that this name is separate from the name used to identify the key in the key container specified in step 1.
exml.AddKeyNameMapping(KeyName, Alg)
exml.AddKeyNameMapping(KeyName, Alg);
Call the DecryptDocument method to decrypt the <EncryptedData> element. This method uses the RSA key to decrypt the session key and automatically uses the session key to decrypt the XML element. It also automatically replaces the <EncryptedData> element with the original plaintext.
exml.DecryptDocument()
exml.DecryptDocument();
Save the XML document.
xmlDoc.Save("test.xml")
xmlDoc.Save("test.xml");
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 an XML element that was encrypted using the techniques described in How to: Encrypt XML Elements with Asymmetric Keys.
Imports System
Imports System.Xml
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Module Program
Sub Main(ByVal args() As String)
' Create an XmlDocument object.
Dim xmlDoc As New XmlDocument()
' Load an XML file into the XmlDocument object.
Try
xmlDoc.PreserveWhitespace = True
xmlDoc.Load("test.xml")
Catch e As Exception
Console.WriteLine(e.Message)
End Try
Dim cspParams As New CspParameters()
cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
' Get the RSA key from the key container. This key will decrypt
' a symmetric key that was imbedded in the XML document.
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
Try
' Decrypt the elements.
Decrypt(xmlDoc, rsaKey, "rsaKey")
' Save the XML document.
xmlDoc.Save("test.xml")
' Display the encrypted XML to the console.
Console.WriteLine()
Console.WriteLine("Decrypted XML:")
Console.WriteLine()
Console.WriteLine(xmlDoc.OuterXml)
Catch e As Exception
Console.WriteLine(e.Message)
Finally
' Clear the RSA key.
rsaKey.Clear()
End Try
Console.ReadLine()
End Sub
Sub Decrypt(ByVal Doc As XmlDocument, ByVal Alg As RSA, ByVal KeyName As String)
' 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
If KeyName Is Nothing Then
Throw New ArgumentNullException("KeyName")
End If
' Create a new EncryptedXml object.
Dim exml As New EncryptedXml(Doc)
' Add a key-name mapping.
' This method can only decrypt documents
' that present the specified key name.
exml.AddKeyNameMapping(KeyName, Alg)
' Decrypt the element.
exml.DecryptDocument()
End Sub
End Module
using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
class Program
{
static void Main(string[] args)
{
// Create an XmlDocument object.
XmlDocument xmlDoc = new XmlDocument();
// Load an XML file into the XmlDocument object.
try
{
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load("test.xml");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
// Get the RSA key from the key container. This key will decrypt
// a symmetric key that was imbedded in the XML document.
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
try
{
// Decrypt the elements.
Decrypt(xmlDoc, rsaKey, "rsaKey");
// Save the XML document.
xmlDoc.Save("test.xml");
// Display the encrypted XML to the console.
Console.WriteLine();
Console.WriteLine("Decrypted XML:");
Console.WriteLine();
Console.WriteLine(xmlDoc.OuterXml);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
// Clear the RSA key.
rsaKey.Clear();
}
Console.ReadLine();
}
public static void Decrypt(XmlDocument Doc, RSA Alg, string KeyName)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
if (Alg == null)
throw new ArgumentNullException("Alg");
if (KeyName == null)
throw new ArgumentNullException("KeyName");
// Create a new EncryptedXml object.
EncryptedXml exml = new EncryptedXml(Doc);
// Add a key-name mapping.
// This method can only decrypt documents
// that present the specified key name.
exml.AddKeyNameMapping(KeyName, Alg);
// Decrypt the element.
exml.DecryptDocument();
}
}
Compiling the Code
To compile this example, you need to include a reference to System.Security.dll.
Include the following namespaces: System.Xml, System.Security.Cryptography, and System.Security.Cryptography.Xml.
Security
Never store a symmetric cryptographic key in plaintext or transfer a symmetric key between machines in plaintext. Additionally, never store or transfer the private key of an asymmetric key pair in plaintext. For more information about symmetric and asymmetric cryptographic keys, see Generating Keys for Encryption and Decryption.
Never embed a key directly into your source code. Embedded keys can be easily read from an assembly by using Ildasm.exe (MSIL Disassembler) or by opening the assembly in a text editor such as Notepad.
When you are done using a cryptographic key, clear it from memory by setting each byte to zero or by calling the Clear method of the managed cryptography class. Cryptographic keys can sometimes be read from memory by a debugger or read from a hard drive if the memory location is paged to disk.
See Also
Tasks
How to: Encrypt XML Elements with Asymmetric Keys
Reference
System.Security.Cryptography.Xml