Compartir a través de


Cómo: Firmar documentos XML con firmas digitales

Puede usar las clases del System.Security.Cryptography.Xml espacio de nombres para firmar un documento XML o parte de un documento XML con una firma digital. Las firmas digitales XML (XMLDSIG) permiten comprobar que los datos no se modificaron después de firmarlos. Para obtener más información sobre el estándar XMLDSIG, consulte la recomendación de World Wide Web Consortium (W3C) xml Signature Syntax and Processing (Sintaxis y procesamiento de firmas XML).

Nota:

El código de este artículo se aplica a Windows.

En el ejemplo de código de este procedimiento se muestra cómo firmar digitalmente un documento XML completo y adjuntar la firma al documento en un <Signature> elemento . En el ejemplo se crea una clave de firma RSA, se agrega la clave a un contenedor de claves segura y, a continuación, se usa la clave para firmar digitalmente un documento XML. A continuación, se puede recuperar la clave para comprobar la firma digital XML o se puede usar para firmar otro documento XML.

Para obtener información sobre cómo comprobar una firma digital XML creada con este procedimiento, vea Cómo: Comprobar las firmas digitales de documentos XML.

Para firmar digitalmente un documento XML

  1. Cree un CspParameters objeto y especifique el nombre del contenedor de claves.

    CspParameters cspParams = new()
    {
        KeyContainerName = "XML_DSIG_RSA_KEY"
    };
    
    Dim cspParams As New CspParameters With {
        .KeyContainerName = "XML_DSIG_RSA_KEY"
    }
    
  2. Genere una clave asimétrica mediante la RSACryptoServiceProvider clase . La clave se guarda automáticamente en el contenedor de claves al pasar el CspParameters objeto al constructor de la RSACryptoServiceProvider clase . Esta clave se usará para firmar el documento XML.

    RSACryptoServiceProvider rsaKey = new(cspParams);
    
    Dim rsaKey As New RSACryptoServiceProvider(cspParams)
    
  3. Cree un XmlDocument objeto cargando un archivo XML desde el disco. El XmlDocument objeto contiene el elemento XML que se va a cifrar.

    XmlDocument xmlDoc = new()
    {
        // Load an XML file into the XmlDocument object.
        PreserveWhitespace = true
    };
    xmlDoc.Load("test.xml");
    
    ' Load an XML file into the XmlDocument object.
    Dim xmlDoc As New XmlDocument With {
        .PreserveWhitespace = True
    }
    xmlDoc.Load("test.xml")
    
  4. Cree un nuevo objeto SignedXml y pase el objeto XmlDocument a este.

    SignedXml signedXml = new(xmlDoc)
    {
    
    Dim signedXml As New SignedXml(xmlDoc)
    
  5. Agregue la clave RSA de firma al SignedXml objeto .

        SigningKey = rsaKey
    };
    
    signedXml.SigningKey = rsaKey
    
  6. Cree un Reference objeto que describa qué firmar. Para firmar todo el documento, establezca la propiedad Uri a "".

    // Create a reference to be signed.
    Reference reference = new()
    {
        Uri = ""
    };
    
    ' Create a reference to be signed.
    Dim reference As New Reference()
    reference.Uri = ""
    
  7. Agregue un XmlDsigEnvelopedSignatureTransform objeto al Reference objeto . Una transformación permite al comprobador representar los datos XML de la misma manera que el firmante usó. Los datos XML se pueden representar de diferentes maneras, por lo que este paso es fundamental para la comprobación.

    XmlDsigEnvelopedSignatureTransform env = new();
    reference.AddTransform(env);
    
    Dim env As New XmlDsigEnvelopedSignatureTransform()
    reference.AddTransform(env)
    
  8. Agregue el Reference objeto al SignedXml objeto .

    signedXml.AddReference(reference);
    
    signedXml.AddReference(reference)
    
  9. Calcule la firma llamando al ComputeSignature método .

    signedXml.ComputeSignature();
    
    signedXml.ComputeSignature()
    
  10. Recupere la representación XML de la firma (un <Signature> elemento) y guárdela en un nuevo XmlElement objeto.

    XmlElement xmlDigitalSignature = signedXml.GetXml();
    
    Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
    
  11. Anexe el elemento al XmlDocument objeto .

    xmlDoc.DocumentElement?.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
    
    xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, True))
    
  12. Guarde el documento.

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

Ejemplo

En este ejemplo se supone que existe un archivo denominado test.xml en el mismo directorio que el programa compilado. Puede colocar el siguiente CÓDIGO XML en un archivo denominado test.xml y usarlo con este ejemplo.

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

[SupportedOSPlatform("Windows")]
public class SignXML
{
    public static void Main(String[] args)
    {
        try
        {
            // Create a new CspParameters object to specify
            // a key container.
            CspParameters cspParams = new()
            {
                KeyContainerName = "XML_DSIG_RSA_KEY"
            };

            // Create a new RSA signing key and save it in the container.
            RSACryptoServiceProvider rsaKey = new(cspParams);

            // Create a new XML document.
            XmlDocument xmlDoc = new()
            {
                // Load an XML file into the XmlDocument object.
                PreserveWhitespace = true
            };
            xmlDoc.Load("test.xml");

            // Sign the XML document.
            SignXml(xmlDoc, rsaKey);

            Console.WriteLine("XML file signed.");

            // Save the document.
            xmlDoc.Save("test.xml");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    // Sign an XML file.
    // This document cannot be verified unless the verifying
    // code has the key with which it was signed.
    public static void SignXml(XmlDocument xmlDoc, RSA rsaKey)
    {
        // Check arguments.
        if (xmlDoc == null)
            throw new ArgumentException(null, nameof(xmlDoc));
        if (rsaKey == null)
            throw new ArgumentException(null, nameof(rsaKey));

        // Create a SignedXml object.
        SignedXml signedXml = new(xmlDoc)
        {

            // Add the key to the SignedXml document.
            SigningKey = rsaKey
        };

        // Create a reference to be signed.
        Reference reference = new()
        {
            Uri = ""
        };

        // Add an enveloped transformation to the reference.
        XmlDsigEnvelopedSignatureTransform env = new();
        reference.AddTransform(env);

        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);

        // Compute the signature.
        signedXml.ComputeSignature();

        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();

        // Append the element to the XML document.
        xmlDoc.DocumentElement?.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
    }
}
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Xml

Module SignXML
    Sub Main(ByVal args() As String)
        Try
            ' Create a new CspParameters object to specify
            ' a key container.
            Dim cspParams As New CspParameters With {
                .KeyContainerName = "XML_DSIG_RSA_KEY"
            }
            ' Create a new RSA signing key and save it in the container. 
            Dim rsaKey As New RSACryptoServiceProvider(cspParams)
            ' Create a new XML document.
            ' Load an XML file into the XmlDocument object.
            Dim xmlDoc As New XmlDocument With {
                .PreserveWhitespace = True
            }
            xmlDoc.Load("test.xml")
            ' Sign the XML document. 
            SignXml(xmlDoc, rsaKey)

            Console.WriteLine("XML file signed.")

            ' Save the document.
            xmlDoc.Save("test.xml")
        Catch e As Exception
            Console.WriteLine(e.Message)
        End Try
    End Sub

    ' Sign an XML file. 
    ' This document cannot be verified unless the verifying 
    ' code has the key with which it was signed.
    Sub SignXml(ByVal xmlDoc As XmlDocument, ByVal rsaKey As RSA)
        ' Check arguments.
        If xmlDoc Is Nothing Then
            Throw New ArgumentException(
                "The XML doc cannot be nothing.", NameOf(xmlDoc))
        End If
        If rsaKey Is Nothing Then
            Throw New ArgumentException(
                "The RSA key cannot be nothing.", NameOf(rsaKey))
        End If
        ' Create a SignedXml object.
        Dim signedXml As New SignedXml(xmlDoc)
        ' Add the key to the SignedXml document.
        signedXml.SigningKey = rsaKey
        ' Create a reference to be signed.
        Dim reference As New Reference()
        reference.Uri = ""
        ' Add an enveloped transformation to the reference.
        Dim env As New XmlDsigEnvelopedSignatureTransform()
        reference.AddTransform(env)
        ' Add the reference to the SignedXml object.
        signedXml.AddReference(reference)
        ' Compute the signature.
        signedXml.ComputeSignature()
        ' Get the XML representation of the signature and save
        ' it to an XmlElement object.
        Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
        ' Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, True))
    End Sub
End Module

Compilar el código

Seguridad de .NET

Nunca almacene ni transfiera la clave privada de un par de claves asimétricas en texto no cifrado. Para obtener más información sobre las claves criptográficas simétricas y asimétricas, consulte Generación de claves para cifrado y descifrado.

Nunca inserte una clave privada directamente en el código fuente. Las claves incrustadas se pueden leer fácilmente desde un ensamblado mediante el Ildasm.exe (desensamblador de IL) o abriendo el ensamblado en un editor de texto como el Bloc de notas.

Consulte también