Compartir a través de


Procedimiento para cifrar elementos XML con claves simétricas

Puede usar las clases en el espacio de nombres System.Security.Cryptography.Xml para cifrar un elemento dentro de un documento XML. El cifrado XML le permite almacenar o transportar información XML confidencial, sin preocuparse de que los datos se puedan leer con facilidad. Este procedimiento cifra un elemento XML mediante el algoritmo AES (Estándar de cifrado avanzado).

Para obtener información sobre la manera de descifrar un elemento XML cifrado mediante este procedimiento, consulta Cómo: Descifrar elementos XML con claves simétricas.

Al usar un algoritmo simétrico como AES para cifrar datos XML, debe usar la misma clave para cifrar y descifrar los datos XML. En el ejemplo de este procedimiento se supone que el código XML cifrado se descifrará con la misma clave y que las partes de cifrado y descifrado están de acuerdo en el algoritmo y la clave que se van a usar. En este ejemplo no se almacena ni se cifra la clave AES dentro del código XML cifrado.

Este ejemplo es idóneo en las situaciones en las que una aplicación necesita cifrar datos en función de una clave de sesión almacenada en memoria o en función de una clave criptográficamente segura derivada de una contraseña. En las situaciones en las que dos o más aplicaciones deben compartir datos XML cifrados, considere el uso de un esquema de cifrado basado en un algoritmo asimétrico o un certificado X.509.

Para cifrar un elemento XML con una clave simétrica

  1. Genere una clave simétrica mediante la clase Aes. Esta clave se usará para cifrar el elemento XML.

    Aes? key = null;
    
    try
    {
        // Create a new AES key.
        key = Aes.Create();
    
    Dim key As Aes = Nothing
    
    Try
        ' Create a new Aes key.
        key = Aes.Create()
    
  2. Cree un objeto XmlDocument cargando un archivo XML del disco. El objeto XmlDocument contiene el elemento XML que se va a cifrar.

    // Load an XML document.
    XmlDocument xmlDoc = new()
    {
        PreserveWhitespace = true
    };
    xmlDoc.Load("test.xml");
    
    ' Load an XML document.
    Dim xmlDoc As New XmlDocument()
    xmlDoc.PreserveWhitespace = True
    xmlDoc.Load("test.xml")
    
  3. Busque el elemento especificado en el objeto XmlDocument y cree un objeto XmlElement nuevo para representar el elemento que desea cifrar. En este ejemplo, el elemento "creditcard" está cifrado.

    XmlElement? elementToEncrypt = Doc.GetElementsByTagName(ElementName)[0] as XmlElement;
    
    Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementName)(0)
    
  4. Cree una nueva instancia de la clase EncryptedXml y úsela para cifrar el XmlElement con la clave simétrica. El método EncryptData devuelve el elemento cifrado como una matriz de bytes cifrados.

    EncryptedXml eXml = new();
    
    byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, Key, false);
    
    Dim eXml As New EncryptedXml()
    
    Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, Key, False)
    
  5. Construya un objeto EncryptedData y rellénelo con el identificador de dirección URL del elemento XML cifrado. Este identificador de dirección URL permite que una entidad descifradora sepa que el código XML contiene un elemento cifrado. Puede usar el campo XmlEncElementUrl para especificar el identificador de dirección URL.

    EncryptedData edElement = new()
    {
        Type = EncryptedXml.XmlEncElementUrl
    };
    
    Dim edElement As New EncryptedData()
    edElement.Type = EncryptedXml.XmlEncElementUrl
    
  6. Cree un objeto EncryptionMethod inicializado en el identificador de dirección URL del algoritmo criptográfico usado para generar la clave. Pase el objeto EncryptionMethod a la propiedad EncryptionMethod.

    string? encryptionMethod;
    if (Key is Aes)
    {
        encryptionMethod = EncryptedXml.XmlEncAES256Url;
    }
    else
    {
        // Throw an exception if the transform is not AES
        throw new CryptographicException("The specified algorithm is not supported or not recommended for XML Encryption.");
    }
    
    edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);
    
    Dim encryptionMethod As String = Nothing
    
    If TypeOf Key Is Aes Then
        encryptionMethod = EncryptedXml.XmlEncAES256Url
    Else
        ' Throw an exception if the transform is not in the previous categories
        Throw New CryptographicException("The specified algorithm is not supported or not recommended for XML Encryption.")
    End If
    
    edElement.EncryptionMethod = New EncryptionMethod(encryptionMethod)
    
  7. Agregue los datos de elementos cifrados al objeto EncryptedData.

    edElement.CipherData.CipherValue = encryptedElement;
    
    edElement.CipherData.CipherValue = encryptedElement
    
  8. Reemplace el elemento del objeto XmlDocument original por el elemento EncryptedData.

    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    
    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
    

Ejemplo

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

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

            try
            {
                // Create a new AES key.
                key = Aes.Create();
                // Load an XML document.
                XmlDocument xmlDoc = new()
                {
                    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
            {
                key?.Clear();
            }
        }

        public static void Encrypt(XmlDocument Doc, string ElementName, SymmetricAlgorithm Key)
        {
            // Check the arguments.
            ArgumentNullException.ThrowIfNull(Doc);
            ArgumentNullException.ThrowIfNull(ElementName);
            ArgumentNullException.ThrowIfNull(Key);

            ////////////////////////////////////////////////
            // Find the specified element in the XmlDocument
            // object and create a new XmlElement 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();

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

            EncryptedData edElement = new()
            {
                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;
            if (Key is Aes)
            {
                encryptionMethod = EncryptedXml.XmlEncAES256Url;
            }
            else
            {
                // Throw an exception if the transform is not AES
                throw new CryptographicException("The specified algorithm is not supported or not recommended 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.
            ArgumentNullException.ThrowIfNull(Doc);
            ArgumentNullException.ThrowIfNull(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();
            edElement.LoadXml(encryptedElement);

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

            // 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);
        }
    }
}
Imports System.Xml
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml

Module Program

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

        Try
            ' Create a new Aes key.
            key = Aes.Create()
            ' 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.  
        ArgumentNullException.ThrowIfNull(Doc)
        ArgumentNullException.ThrowIfNull(ElementName)
        ArgumentNullException.ThrowIfNull(Key)

        ''''''''''''''''''''''''''''''''''''''''''''''''''
        ' 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 Aes Then
            encryptionMethod = EncryptedXml.XmlEncAES256Url
        Else
            ' Throw an exception if the transform is not in the previous categories
            Throw New CryptographicException("The specified algorithm is not supported or not recommended 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


    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

Compilar el código

Seguridad de .NET

No almacene nunca una clave criptográfica en texto sin formato ni transfiera una clave entre equipos en texto sin formato. En su lugar, use un contenedor de claves seguro para almacenar las claves criptográficas.

Cuando termine de usar una clave criptográfica, bórrela de la memoria estableciendo cada byte en cero o llamando al método Clear de la clase criptográfica administrada.

Consulte también