Cómo: Descifrar elementos XML con claves simétricas
Actualización: noviembre 2007
Puede utilizar las clases del espacio de nombres System.Security.Cryptography.Xml para cifrar un elemento dentro de un documento XML. XML Encryption le permite almacenar o transportar información XML confidencial, sin tener que preocuparse de que los datos puedan leerse con facilidad. En este ejemplo de código, se descifra un elemento XML mediante el algoritmo del estándar de cifrado avanzado (AES), también conocido como Rijndael.
Para obtener información sobre la forma de cifrar un elemento XML mediante este procedimiento, vea Cómo: Cifrar elementos XML con claves simétricas.
Cuando se utiliza un algoritmo asimétrico para cifrar datos XML, como el algoritmo AES, debe utilizarse la misma clave para cifrar y descifrar los datos. En el ejemplo de este procedimiento, se asume que se ha utilizado la misma clave para cifrar los datos XML y que las partes implicadas en las operaciones de cifrado y descifrado coinciden en el uso del algoritmo y la clave. En este ejemplo, la clave AES no se almacena ni se cifra dentro del XML cifrado.
Se trata de un ejemplo adecuado para situaciones en las que una única aplicación tiene que cifrar datos basándose en una clave de sesión almacenada en la memoria o en una clave criptográficamente segura derivada de una contraseña. Para situaciones en las que dos o más aplicaciones tienen que compartir datos XML cifrados, se puede contemplar el uso de un esquema de cifrado basado en un algoritmo asimétrico o en un certificado X.509.
Para descifrar un elemento XML con una clave simétrica
Cifre un elemento XML con la clave previamente generada mediante las técnicas que se describen en Cómo: Cifrar elementos XML con claves simétricas.
Busque el elemento <EncryptedData> (definido por el estándar XML Encryption) en un objeto XmlDocument que contenga XML cifrado y cree un nuevo objeto XmlElement que represente dicho elemento.
Dim encryptedElement As XmlElement = Doc.GetElementsByTagName("EncryptedData")(0)
XmlElement encryptedElement = Doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;
Cree un objeto EncryptedData cargando los datos XML sin procesar del objeto XmlElement previamente creado.
Dim edElement As New EncryptedData() edElement.LoadXml(encryptedElement)
EncryptedData edElement = new EncryptedData(); edElement.LoadXml(encryptedElement);
Cree un nuevo objeto EncryptedXml y utilícelo para descifrar los datos XML utilizando la misma clave que se haya utilizado para el cifrado.
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);
Reemplace el elemento cifrado por el elemento de texto sin formato recién descifrado dentro del documento XML.
exml.ReplaceData(encryptedElement, rgbOutput)
exml.ReplaceData(encryptedElement, rgbOutput);
Ejemplo
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);
}
}
}
En este ejemplo se supone que existe un archivo denominado "test.xml" en el mismo directorio que el programa compilado. También se supone que "test.xml" contiene un elemento "creditcard". Puede colocar el siguiente elemento XML en un archivo denominado test.xml y utilizarlo con este ejemplo.
<root>
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
Compilar el código
Para compilar este ejemplo, es necesario incluir una referencia a System.Security.dll.
Incluya estos espacios de nombres: System.Xml, System.Security.Cryptography y System.Security.Cryptography.Xml.
Seguridad
No se debe almacenar nunca una clave criptográfica en texto sin formato, ni se debe transferir nunca una clave entre equipos en texto sin formato.
Cuando haya terminado de utilizar una clave criptográfica simétrica, elimínela de la memoria estableciendo cada byte en cero o llamando al método Clear de la clase criptográfica administrada.
Vea también
Tareas
Cómo: Cifrar elementos XML con claves simétricas
Referencia
System.Security.Cryptography.Xml