Vorgehensweise: Signieren von XML-Dokumenten mit digitalen Signaturen

Um ein XML-Dokument teilweise oder vollständig mit einer digitalen Signatur zu versehen, können Sie die Klassen im System.Security.Cryptography.Xml-Namespace verwenden. Über digitale XML-Signaturen (XMLDSIG) können Sie sich vergewissern, dass Daten nicht mehr geändert wurden, nachdem sie signiert wurden. Weitere Informationen zum XMLDSIG-Standard finden Sie in der W3C-Empfehlung (World Wide Web Consortium) XML Signature Syntax and Processing.

Hinweis

Der Code in diesem Artikel gilt für Windows.

Im Codebeispiel in dieser Vorgehensweise wird veranschaulicht, wie ein gesamtes XML-Dokument digital signiert und die Signatur dem Dokument in einem <Signature>-Element angefügt wird. Im Beispiel wird ein RSA-Signaturschlüssel erstellt, wird der Schlüssel einem sicheren Schlüsselcontainer hinzugefügt und wird der Schlüssel dann verwendet, um ein XML-Dokument digital zu signieren. Der Schlüssel kann danach abgerufen werden, um die digitale Signatur des XML-Dokuments zu überprüfen oder ein anderes XML-Dokument zu signieren.

Informationen dazu, wie eine digitale Signatur überprüft wird, die mit dieser Vorgehensweise erstellt wurde, finden Sie unter Überprüfen der digitalen Signaturen von XML-Dokumenten.

So signieren Sie ein XML-Dokument digital

  1. Erstellen Sie ein CspParameters-Objekt, und geben Sie den Namen des Schlüsselcontainers an.

    CspParameters cspParams = new()
    {
        KeyContainerName = "XML_DSIG_RSA_KEY"
    };
    
    Dim cspParams As New CspParameters With {
        .KeyContainerName = "XML_DSIG_RSA_KEY"
    }
    
  2. Generieren Sie mit der RSACryptoServiceProvider-Klasse einen asymmetrischen Schlüssel. Der Schlüssel wird automatisch im Schlüsselcontainer gespeichert, wenn Sie das CspParameters-Objekt an den Konstruktor der RSACryptoServiceProvider-Klasse übergeben. Dieser Schlüssel wird zum Signieren des XML-Dokuments verwendet.

    RSACryptoServiceProvider rsaKey = new(cspParams);
    
    Dim rsaKey As New RSACryptoServiceProvider(cspParams)
    
  3. Erstellen Sie ein XmlDocument-Objekt, indem Sie eine XML-Datei von einem Datenträger laden. Das XmlDocument-Objekt enthält das zu verschlüsselnde XML-Element.

    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. Erstellen Sie ein neues SignedXml-Objekt, und übergeben Sie diesem das XmlDocument-Objekt.

    SignedXml signedXml = new(xmlDoc)
    {
    
    Dim signedXml As New SignedXml(xmlDoc)
    
  5. Fügen Sie den RSA-Signaturschlüssel dem SignedXml-Objekt hinzu.

        SigningKey = rsaKey
    };
    
    signedXml.SigningKey = rsaKey
    
  6. Erstellen Sie ein Reference-Objekt, das beschreibt, was signiert werden soll. Um das gesamte Dokument zu signieren, legen Sie die Uri-Eigenschaft auf "" fest.

    // Create a reference to be signed.
    Reference reference = new()
    {
        Uri = ""
    };
    
    ' Create a reference to be signed.
    Dim reference As New Reference()
    reference.Uri = ""
    
  7. Fügen Sie dem Reference-Objekt ein XmlDsigEnvelopedSignatureTransform-Objekt hinzu. Eine Transformation ermöglicht es dem Prüfer, die XML-Daten auf genau die Weise darzustellen, die der Signaturgeber verwendet hat. XML-Daten können auf unterschiedliche Weise dargestellt werden, weshalb dieser Schritt für die Überprüfung unverzichtbar ist.

    XmlDsigEnvelopedSignatureTransform env = new();
    reference.AddTransform(env);
    
    Dim env As New XmlDsigEnvelopedSignatureTransform()
    reference.AddTransform(env)
    
  8. Fügen Sie dem SignedXml-Objekt das Reference-Objekt hinzu.

    signedXml.AddReference(reference);
    
    signedXml.AddReference(reference)
    
  9. Berechnen Sie die Signatur, indem Sie die ComputeSignature-Methode aufrufen.

    signedXml.ComputeSignature();
    
    signedXml.ComputeSignature()
    
  10. Rufen Sie die XML-Darstellung der Signatur (ein <Signature>-Element) ab, und speichern Sie die Darstellung in einem neuen XmlElement-Objekt.

    XmlElement xmlDigitalSignature = signedXml.GetXml();
    
    Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
    
  11. Fügen Sie das Element an das XmlDocument-Objekt an.

    xmlDoc.DocumentElement?.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
    
    xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, True))
    
  12. Speichern Sie das Dokument.

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

Beispiel

Für dieses Beispiel wird angenommen, dass eine Datei namens test.xml im selben Verzeichnis wie das kompilierte Programm vorhanden ist. Sie können den folgenden XML-Code in eine Datei namens test.xml einfügen und mit diesem Beispiel verwenden.

<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

Kompilieren des Codes

.NET-Sicherheit

Sie sollten den privaten Schlüssel eines asymmetrischen Schlüsselpaars niemals in Klartext speichern oder übertragen. Weitere Informationen zu symmetrischen und asymmetrischen kryptografischen Schlüsseln finden Sie unter Generieren von Schlüsseln für die Ver- und Entschlüsselung.

Sie sollten einen privaten Schlüssel niemals direkt in Ihren Quellcode einbetten. Eingebettete Schlüssel können problemlos aus einer Assembly gelesen werden, indem Sie Ildasm.exe (IL-Disassembler) verwenden oder die Assembly in einem Text-Editor öffnen.

Siehe auch