Compartir a través de


Cómo: Cifrar elementos XML con certificados X.509

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 es una forma estándar de intercambiar o almacenar datos XML cifrados, sin tener que preocuparse de que puedan leerse con facilidad. Para obtener más información sobre el estándar XML Encryption, vea la especificación del World Wide Web Consortium (W3C) sobre XML Encryption en la dirección http://www.w3.org/TR/xmldsig-core/.

Puede utilizar XML Encryption para reemplazar cualquier elemento o documento XML por un elemento <EncryptedData> que contenga datos XML cifrados. El elemento <EncryptedData> puede contener subelementos con información sobre las claves y procesos utilizados durante el cifrado. XML Encryption permite que un documento contenga varios elementos cifrados y permite cifrar un elemento varias veces. En el ejemplo de código de este procedimiento se muestra la forma crear un elemento <EncryptedData> junto con otros subelementos que se pueden utilizar posteriormente, durante la operación de descifrado.

En este ejemplo, se cifra un elemento XML utilizando dos claves. Se genera un certificado X.509 de prueba mediante Herramienta Creación de certificados (Makecert.exe) y se guarda el certificado en un almacén de certificados. A continuación, en el ejemplo, el certificado se recupera mediante programación y se utiliza para cifrar un elemento XML mediante el método Encrypt. Internamente, el método Encrypt crea una clave de sesión independiente, que se utiliza para cifrar el documento XML. Este método cifra la clave de sesión y la guarda junto con el elemento XML cifrado, dentro de un nuevo elemento <EncryptedData>.

Para descifrar el elemento XML, hay que llamar simplemente al método DecryptDocument, que recupera automáticamente el certificado X.509 del almacén y realiza las operaciones de descifrado necesarias. Para obtener más información sobre la forma de descifrar un elemento XML que se haya cifrado mediante este procedimiento, vea Cómo: Descifrar elementos XML con certificados X.509.

Se trata de un ejemplo adecuado para situaciones en las que hay varias aplicaciones que necesitan compartir datos cifrados o situaciones en las que una aplicación necesita guardar datos cifrados entre los distintos momentos en que se ejecuta.

Para cifrar un elemento XML con un certificado X.509

  1. Utilice Herramienta Creación de certificados (Makecert.exe) para generar un certificado X.509 de prueba y colocarlo en el almacén de usuario local. Debe generar una clave de intercambio y convertirla en una clave exportable. Ejecute el siguiente comando:

    makecert -r -pe -n "CN=XML_ENC_TEST_CERT" -b 01/01/2005 -e 01/01/2010 -sky exchange -ss my
    
  2. Cree un objeto X509Store e inicialícelo para abrir el almacén de usuario actual.

    Dim store As New X509Store(StoreLocation.CurrentUser)
    
    X509Store store = new X509Store(StoreLocation.CurrentUser);
    
  3. Abra el almacén en modo de sólo lectura.

    store.Open(OpenFlags.ReadOnly)
    
    store.Open(OpenFlags.ReadOnly);
    
  4. Inicialice un objeto X509Certificate2Collection con todos los certificados del almacén.

    Dim certCollection As X509Certificate2Collection = store.Certificates
    
    X509Certificate2Collection certCollection = store.Certificates;
    
  5. Enumere los certificados del almacén y busque el certificado con el nombre adecuado. En este ejemplo, el certificado se denomina "CN=XML_ENC_TEST_CERT".

    Dim cert As X509Certificate2 = Nothing
    
    ' Loop through each certificate and find the certificate 
    ' with the appropriate name.
    Dim c As X509Certificate2
    For Each c In certCollection
        If c.Subject = "CN=XML_ENC_TEST_CERT" Then
            cert = c
    
            Exit For
        End If
    Next c
    
    X509Certificate2 cert = null;
    
    // Loop through each certificate and find the certificate 
    // with the appropriate name.
    foreach (X509Certificate2 c in certCollection)
    {
        if (c.Subject == "CN=XML_ENC_TEST_CERT")
        {
            cert = c;
    
            break;
        }
    }
    
  6. Una vez localizado el certificado, cierre el almacén.

    store.Close()
    
    store.Close();
    
  7. Cree un objeto XmlDocument cargando un archivo XML desde el disco. El objeto XmlDocument contiene el elemento XML que se va a cifrar.

    Dim xmlDoc As New XmlDocument()
    
    XmlDocument xmlDoc = new XmlDocument();
    
  8. Busque el elemento especificado en el objeto XmlDocument y cree un nuevo objeto XmlElement que represente el elemento que desea cifrar. En este ejemplo, se cifra el elemento "creditcard".

    Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(0)
    
    
    XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
    
  9. Cree una nueva instancia de la clase EncryptedXml y utilícela para cifrar el elemento especificado utilizando el certificado X.509. El método Encrypt devuelve el elemento cifrado como un objeto EncryptedData.

    Dim eXml As New EncryptedXml()
    
    ' Encrypt the element.
    Dim edElement As EncryptedData = eXml.Encrypt(elementToEncrypt, Cert)
    
    EncryptedXml eXml = new EncryptedXml();
    
    // Encrypt the element.
    EncryptedData edElement = eXml.Encrypt(elementToEncrypt, Cert);
    
  10. Reemplace el elemento del objeto XmlDocument original por el elemento EncryptedData.

    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
    
    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    
  11. Guarde el objeto XmlDocument.

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

Ejemplo

Imports System
Imports System.Xml
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates



Module Program

    Sub Main(ByVal args() As String)
        Try
            ' Create an XmlDocument object.
            Dim xmlDoc As New XmlDocument()
            ' Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load("test.xml")

            ' Open the X.509 "Current User" store in read only mode.
            Dim store As New X509Store(StoreLocation.CurrentUser)
            store.Open(OpenFlags.ReadOnly)
            ' Place all certificates in an X509Certificate2Collection object.
            Dim certCollection As X509Certificate2Collection = store.Certificates
            Dim cert As X509Certificate2 = Nothing

            ' Loop through each certificate and find the certificate 
            ' with the appropriate name.
            Dim c As X509Certificate2
            For Each c In certCollection
                If c.Subject = "CN=XML_ENC_TEST_CERT" Then
                    cert = c

                    Exit For
                End If
            Next c
            If cert Is Nothing Then
                Throw New CryptographicException("The X.509 certificate could not be found.")
            End If

            ' Close the store.
            store.Close()
            ' Encrypt the "creditcard" element.
            Encrypt(xmlDoc, "creditcard", cert)

            ' Save the XML document.
            xmlDoc.Save("test.xml")
            ' Display the encrypted XML to the console.
            Console.WriteLine("Encrypted XML:")
            Console.WriteLine()
            Console.WriteLine(xmlDoc.OuterXml)

        Catch e As Exception
            Console.WriteLine(e.Message)
        End Try

    End Sub 'Main


    Sub Encrypt(ByVal Doc As XmlDocument, ByVal ElementToEncryptName As String, ByVal Cert As X509Certificate2)
        ' Check the arguments.  
        If Doc Is Nothing Then
            Throw New ArgumentNullException("Doc")
        End If
        If ElementToEncryptName Is Nothing Then
            Throw New ArgumentNullException("ElementToEncrypt")
        End If
        If Cert Is Nothing Then
            Throw New ArgumentNullException("Cert")
        End If
        ''''''''''''''''''''''''''''''''''''''''''''''''
        ' Find the specified element in the XmlDocument
        ' object and create a new XmlElemnt object.
        ''''''''''''''''''''''''''''''''''''''''''''''''
        Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(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 
        ' X.509 Certificate.
        ''''''''''''''''''''''''''''''''''''''''''''''''
        Dim eXml As New EncryptedXml()

        ' Encrypt the element.
        Dim edElement As EncryptedData = eXml.Encrypt(elementToEncrypt, Cert)
        ''''''''''''''''''''''''''''''''''''''''''''''''
        ' Replace the element from the original XmlDocument
        ' object with the EncryptedData element.
        ''''''''''''''''''''''''''''''''''''''''''''''''
        EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
    End Sub
End Module
using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            // Create an XmlDocument object.
            XmlDocument xmlDoc = new XmlDocument();

            // Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load("test.xml");

            // Open the X.509 "Current User" store in read only mode.
            X509Store store = new X509Store(StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);

            // Place all certificates in an X509Certificate2Collection object.
            X509Certificate2Collection certCollection = store.Certificates;

            X509Certificate2 cert = null;

            // Loop through each certificate and find the certificate 
            // with the appropriate name.
            foreach (X509Certificate2 c in certCollection)
            {
                if (c.Subject == "CN=XML_ENC_TEST_CERT")
                {
                    cert = c;

                    break;
                }
            }

            if (cert == null)
            {
                throw new CryptographicException("The X.509 certificate could not be found.");
            }

            // Close the store.
            store.Close();

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

            // Save the XML document.
            xmlDoc.Save("test.xml");

            // Display the encrypted XML to the console.
            Console.WriteLine("Encrypted XML:");
            Console.WriteLine();
            Console.WriteLine(xmlDoc.OuterXml);

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

    }

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

        ////////////////////////////////////////////////
        // Find the specified element in the XmlDocument
        // object and create a new XmlElemnt object.
        ////////////////////////////////////////////////

        XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[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 
        // X.509 Certificate.
        //////////////////////////////////////////////////

        EncryptedXml eXml = new EncryptedXml();

        // Encrypt the element.
        EncryptedData edElement = eXml.Encrypt(elementToEncrypt, Cert);

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

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

Seguridad

El certificado X.509 de este ejemplo se utiliza únicamente con propósito de prueba. Las aplicaciones deben utilizar un certificado X.509 generado por una entidad de certificación de confianza o utilizar un certificado generado por Microsoft Windows Certificate Server.

Vea también

Tareas

Cómo: Descifrar elementos XML con certificados X.509

Referencia

System.Security.Cryptography.Xml

Otros recursos

Cifrado XML y firmas digitales