Procedimiento para descifrar elementos XML con claves asimétricasHow to: Decrypt XML Elements with Asymmetric Keys

Puede usar las clases en el espacio de nombres System.Security.Cryptography.Xml para cifrar y descifrar un elemento dentro de un documento XML.You can use the classes in the System.Security.Cryptography.Xml namespace to encrypt and decrypt an element within an XML document. El cifrado XML es un método estándar para intercambiar o almacenar datos XML cifrados sin preocuparse de que los datos puedan leerse con facilidad.XML Encryption is a standard way to exchange or store encrypted XML data, without worrying about the data being easily read. Para obtener más información sobre el estándar de cifrado XML, vea la recomendación del World Wide Web Consortium (W3C) sintaxis y procesamiento de firmas XML.For more information about the XML Encryption standard, see the World Wide Web Consortium (W3C) recommendation XML Signature Syntax and Processing.

Nota

El código de este artículo se aplica a Windows.The code in this article applies to Windows.

El ejemplo de este procedimiento descifra un elemento XML cifrado mediante los métodos descritos en Cómo: cifrar elementos XML con claves asimétricas.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. Busca un elemento de EncryptedData> de <, descifra el elemento y, a continuación, reemplaza el elemento por el elemento XML de texto sin formato original.It finds an <EncryptedData> element, decrypts the element, and then replaces the element with the original plaintext XML element.

En este ejemplo se descifra un elemento XML mediante dos claves.This example decrypts an XML element using two keys. Recupera una clave privada RSA generada previamente a partir de un contenedor de claves y, a continuación, usa la clave RSA para descifrar una clave de sesión almacenada en el EncryptedKey elemento <> del EncryptedData elemento> <.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. Luego, el ejemplo usa la clave de sesión para descifrar el elemento XML.The example then uses the session key to decrypt the XML element.

Este ejemplo resulta adecuado en aquellas situaciones en las que varias aplicaciones tienen que compartir datos cifrados o en las que una aplicación tiene que guardar datos cifrados entre los intervalos en los que se ejecuta.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.

Para descifrar un elemento XML con una clave asimétricaTo decrypt an XML element with an asymmetric key

  1. Cree un objeto CspParameters y especifique el nombre del contenedor de claves.Create a CspParameters object and specify the name of the key container.

    CspParameters cspParams = new CspParameters();
    cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
    
    Dim cspParams As New CspParameters()
    cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
    
  2. Recupere una clave asimétrica previamente generada desde el contenedor mediante el objeto RSACryptoServiceProvider.Retrieve a previously generated asymmetric key from the container using the RSACryptoServiceProvider object. La clave se recupera automáticamente del contenedor de claves al pasar el objeto CspParameters al constructor RSACryptoServiceProvider.The key is automatically retrieved from the key container when you pass the CspParameters object to the RSACryptoServiceProvider constructor.

    RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
    
    Dim rsaKey As New RSACryptoServiceProvider(cspParams)
    
  3. Cree un objeto EncryptedXml nuevo para descifrar el documento.Create a new EncryptedXml object to decrypt the document.

    // Create a new EncryptedXml object.
    EncryptedXml exml = new EncryptedXml(Doc);
    
    ' Create a new EncryptedXml object.
    Dim exml As New EncryptedXml(Doc)
    
  4. Agregue una asignación de clave/nombre para asociar la clave RSA al elemento del documento que se debe descifrar.Add a key/name mapping to associate the RSA key with the element within the document that should be decrypted. Debe usar el mismo nombre para la clave que usó al cifrar el documento.You must use the same name for the key that you used when you encrypted the document. Tenga en cuenta que este nombre es independiente del que haya usado para identificar la clave en el contenedor de claves especificado en el paso 1.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)
    
  5. Llame al DecryptDocument método para descifrar el elemento de> de <EncryptedData .Call the DecryptDocument method to decrypt the <EncryptedData> element. Este método usa la clave RSA para descifrar la clave de sesión y la usa automáticamente para descifrar el elemento XML.This method uses the RSA key to decrypt the session key and automatically uses the session key to decrypt the XML element. También reemplaza automáticamente el elemento <EncryptedData> por el texto sin formato original.It also automatically replaces the <EncryptedData> element with the original plaintext.

    exml.DecryptDocument();
    
    exml.DecryptDocument()
    
  6. Guarde el documento XML.Save the XML document.

    xmlDoc.Save("test.xml");
    
    xmlDoc.Save("test.xml")
    

EjemploExample

En este ejemplo se supone que un archivo llamado test.xml se encuentra en el mismo directorio que el programa compilado.This example assumes that a file named test.xml exists in the same directory as the compiled program. También se supone que test.xml contiene un elemento XML cifrado mediante las técnicas descritas en Cómo: cifrar elementos XML con claves asimétricas.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.


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();
    }
}
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

Compilar el códigoCompiling the Code

Seguridad de .NET.NET Security

No almacene nunca una clave criptográfica simétrica en texto sin formato ni transfiera una clave simétrica entre equipos en texto sin formato.Never store a symmetric cryptographic key in plaintext or transfer a symmetric key between machines in plaintext. Tampoco debe almacenar ni transferir nunca la clave privada de un par de claves asimétricas en texto sin formato.Additionally, never store or transfer the private key of an asymmetric key pair in plaintext. Para obtener más información acerca de las claves criptográficas simétricas y asimétricas, vea generar claves para cifrado y descifrado.For more information about symmetric and asymmetric cryptographic keys, see Generating Keys for Encryption and Decryption.

No inserte nunca una clave directamente en el código fuente.Never embed a key directly into your source code. Las claves incrustadas se pueden leer fácilmente desde un ensamblado mediante Ildasm.exe (desensamblador de IL) o abriendo el ensamblado en un editor de texto como el Bloc de notas.Embedded keys can be easily read from an assembly by using Ildasm.exe (IL Disassembler) or by opening the assembly in a text editor such as Notepad.

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.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. A veces, las claves criptográficas se pueden leer desde la memoria con un depurador o desde un disco duro si la ubicación de memoria se pagina en el disco.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.

Vea tambiénSee also