Compartir a través de


Procedimiento para cifrar elementos XML con certificados X.509

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 es un método estándar para intercambiar o almacenar datos XML cifrados sin preocuparse de que los datos puedan leerse con facilidad. Para obtener más información sobre el estándar de cifrado XML, vea la especificación de World Wide Web Consortium (W3C) del cifrado XML, que se encuentra en https://www.w3.org/TR/xmldsig-core/.

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

En este ejemplo se cifra un elemento XML mediante dos claves. En el ejemplo se recupera un certificado mediante programación y se usa para cifrar un elemento XML mediante el método Encrypt. Internamente, el método Encrypt crea una clave de sesión independiente y la usa para cifrar el documento XML. Este método cifra la clave de sesión y la guarda junto con el XML cifrado dentro de un nuevo elemento <EncryptedData>.

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

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.

Para cifrar un elemento XML con un certificado X.509

Para ejecutar este ejemplo, debe crear un certificado de prueba y guardarlo en un almacén de certificados. Las instrucciones para esa tarea solo se proporcionan para la Herramienta de creación de certificados (Makecert.exe) de Windows.

  1. Use 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 debe hacerla exportable. Ejecute el siguiente comando:

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

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

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

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

    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;
        }
    }
    
    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
    
  6. Cierre el almacén después de localizar el certificado.

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

    XmlDocument xmlDoc = new XmlDocument();
    
    Dim xmlDoc As New XmlDocument()
    
  8. 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(ElementToEncrypt)[0] as XmlElement;
    
    Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(0)
    
    
  9. Cree una nueva instancia de la clase EncryptedXml y úsela para cifrar el elemento especificado mediante el certificado X.509. El método Encrypt devuelve el elemento cifrado como un objeto EncryptedData.

    EncryptedXml eXml = new EncryptedXml();
    
    // Encrypt the element.
    EncryptedData edElement = eXml.Encrypt(elementToEncrypt, Cert);
    
    Dim eXml As New EncryptedXml()
    
    ' Encrypt the element.
    Dim edElement As EncryptedData = 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

En este ejemplo se supone que un archivo llamado "test.xml" se encuentra en el mismo directorio que el programa compilado. También se supone que "test.xml" contiene un elemento "creditcard". Puede colocar el siguiente código XML en un archivo llamado test.xml y usarlo con este 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;
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 XmlElement 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);
    }
}
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


    Sub Encrypt(ByVal Doc As XmlDocument, ByVal ElementToEncryptName As String, ByVal Cert As X509Certificate2)
        ' Check the arguments.  
        ArgumentNullException.ThrowIfNull(Doc)
        ArgumentNullException.ThrowIfNull(ElementToEncryptName)
        ArgumentNullException.ThrowIfNull(Cert)
        ''''''''''''''''''''''''''''''''''''''''''''''''
        ' 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

Compilar el código

Seguridad de .NET

El certificado X.509 usado en este ejemplo se usa únicamente para pruebas. Las aplicaciones deben usar un certificado X.509 generado por una autoridad de certificados de confianza.

Consulte también