Vorgehensweise: Überprüfen der digitalen Signaturen von XML-Dokumenten

Um XML-Daten zu überprüfen, die mit einer digitalen Signatur signiert sind, 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-Spezifikation (World Wide Web Consortium) unter https://www.w3.org/TR/xmldsig-core/.

Hinweis

Der Code in diesem Artikel gilt für Windows.

Das Codebeispiel in dieser Vorgehensweise veranschaulicht, wie eine digitale XML-Signatur überprüft wird, die in einem <Signature>-Element enthalten ist. Im Beispiel wird ein öffentlicher RSA-Schlüssel aus einem Schlüsselcontainer abgerufen und anschließend zum Überprüfen der Signatur verwendet.

Informationen zum Erstellen einer digitalen Signatur, die mithilfe dieser Technik überprüft werden kann, finden Sie unter Gewusst wie: Signieren von XML-Dokumenten mit digitalen Signaturen.

So überprüfen Sie die digitale Signatur eines XML-Dokuments

  1. Um das Dokument zu überprüfen, müssen Sie denselben asymmetrischen Schlüssel wie für die Signierung verwenden. Erstellen Sie ein CspParameters-Objekt, und geben Sie den Namen des Schlüsselcontainers an, der zum Signieren verwendet wurde.

    CspParameters cspParams = new()
    {
        KeyContainerName = "XML_DSIG_RSA_KEY"
    };
    
    Dim cspParams As New CspParameters()
    cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
    
  2. Rufen Sie den öffentlichen Schlüssel mit der RSACryptoServiceProvider-Klasse ab. Der Schlüssel wird automatisch nach Name aus dem Schlüsselcontainer geladen, wenn Sie das CspParameters-Objekt an den Konstruktor der RSACryptoServiceProvider-Klasse übergeben.

    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 signierte XML-Dokument, das überprüft werden soll.

    XmlDocument xmlDoc = new()
    {
        // Load an XML file into the XmlDocument object.
        PreserveWhitespace = true
    };
    xmlDoc.Load("test.xml");
    
    Dim xmlDoc As New XmlDocument()
    
    ' Load an XML file into the XmlDocument object.
    xmlDoc.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. Suchen Sie nach dem <signature>-Element, und erstellen Sie ein neues XmlNodeList-Objekt.

    XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
    
    Dim nodeList As XmlNodeList = xmlDoc.GetElementsByTagName("Signature")
    
  6. Laden Sie den XML-Code des ersten <signature>-Elements in das SignedXml-Objekt.

    signedXml.LoadXml((XmlElement?)nodeList[0]);
    
    signedXml.LoadXml(CType(nodeList(0), XmlElement))
    
  7. Überprüfen Sie die Signatur mit der CheckSignature-Methode und dem öffentlichen RSA-Schlüssel. Diese Methode gibt einen booleschen Wert zurück, mit dem Erfolg oder Fehlschlagen des Vorgangs angegeben wird.

    return signedXml.CheckSignature(key);
    
    Return signedXml.CheckSignature(key)
    

Beispiel

Für dieses Beispiel wird angenommen, dass eine Datei namens "test.xml" im selben Verzeichnis wie das kompilierte Programm vorhanden ist. Die Datei "test.xml" muss mit den Techniken signiert werden, die unter Gewusst wie: Signieren von XML-Dokumenten mit digitalen Signaturen beschrieben sind.

using System;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;

[SupportedOSPlatform("Windows")]
public class VerifyXML
{
    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");

            // Verify the signature of the signed XML.
            Console.WriteLine("Verifying signature...");
            bool result = VerifyXml(xmlDoc, rsaKey);

            // Display the results of the signature verification to
            // the console.
            if (result)
            {
                Console.WriteLine("The XML signature is valid.");
            }
            else
            {
                Console.WriteLine("The XML signature is not valid.");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    // Verify the signature of an XML file against an asymmetric
    // algorithm and return the result.
    public static bool VerifyXml(XmlDocument xmlDoc, RSA key)
    {
        // Check arguments.
        if (xmlDoc == null)
             throw new ArgumentException(null, nameof(xmlDoc));
        if (key == null)
            throw new ArgumentException(null, nameof(key));

        // Create a new SignedXml object and pass it
        // the XML document class.
        SignedXml signedXml = new(xmlDoc);

        // Find the "Signature" node and create a new
        // XmlNodeList object.
        XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");

        // Throw an exception if no signature was found.
        if (nodeList.Count <= 0)
        {
            throw new CryptographicException("Verification failed: No Signature was found in the document.");
        }

        // This example only supports one signature for
        // the entire XML document.  Throw an exception
        // if more than one signature was found.
        if (nodeList.Count >= 2)
        {
            throw new CryptographicException("Verification failed: More that one signature was found for the document.");
        }

        // Load the first <signature> node.
        signedXml.LoadXml((XmlElement?)nodeList[0]);

        // Check the signature and return the result.
        return signedXml.CheckSignature(key);
    }
}
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Xml

Module VerifyXML
    Sub Main(ByVal args() As String)
        Try
            ' Create a new CspParameters object to specify
            ' a key container.
            Dim cspParams As New CspParameters()
            cspParams.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.
            Dim xmlDoc As New XmlDocument()

            ' Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load("test.xml")
            ' Verify the signature of the signed XML.
            Console.WriteLine("Verifying signature...")
            Dim result As Boolean = VerifyXml(xmlDoc, rsaKey)

            ' Display the results of the signature verification to 
            ' the console.
            If result Then
                Console.WriteLine("The XML signature is valid.")
            Else
                Console.WriteLine("The XML signature is not valid.")
            End If

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

    ' Verify the signature of an XML file against an asymmetric 
    ' algorithm and return the result.
    Function VerifyXml(ByVal xmlDoc As XmlDocument, ByVal key As RSA) As [Boolean]
        ' Check arguments.
        If xmlDoc Is Nothing Then
            Throw New ArgumentException(
                "The XML doc cannot be nothing.", NameOf(xmlDoc))
        End If
        If key Is Nothing Then
            Throw New ArgumentException(
                "The key cannot be nothing.", NameOf(key))
        End If
        ' Create a new SignedXml object and pass it
        ' the XML document class.
        Dim signedXml As New SignedXml(xmlDoc)
        ' Find the "Signature" node and create a new
        ' XmlNodeList object.
        Dim nodeList As XmlNodeList = xmlDoc.GetElementsByTagName("Signature")
        ' Throw an exception if no signature was found.
        If nodeList.Count <= 0 Then
            Throw New CryptographicException("Verification failed: No Signature was found in the document.")
        End If

        ' This example only supports one signature for
        ' the entire XML document.  Throw an exception 
        ' if more than one signature was found.
        If nodeList.Count >= 2 Then
            Throw New CryptographicException("Verification failed: More that one signature was found for the document.")
        End If

        ' Load the first <signature> node.  
        signedXml.LoadXml(CType(nodeList(0), XmlElement))
        ' Check the signature and return the result.
        Return signedXml.CheckSignature(key)
    End Function
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