Udostępnij za pośrednictwem


Porady: sprawdzanie podpisów cyfrowych w dokumentach XML

Klasy w System.Security.Cryptography.Xml przestrzeni nazw umożliwiają weryfikowanie danych XML podpisanych przy użyciu podpisu cyfrowego. Podpisy cyfrowe XML (XMLDSIG) umożliwiają sprawdzenie, czy dane nie zostały zmienione po jego podpisaniu. Aby uzyskać więcej informacji na temat standardu XMLDSIG, zobacz specyfikację World Wide Web Consortium (W3C) pod adresem https://www.w3.org/TR/xmldsig-core/.

Uwaga

Kod w tym artykule dotyczy systemu Windows.

W przykładzie kodu w tej procedurze pokazano, jak zweryfikować podpis cyfrowy XML zawarty w elemecie <Signature> . Przykład pobiera klucz publiczny RSA z kontenera kluczy, a następnie używa klucza do zweryfikowania podpisu.

Aby uzyskać informacje na temat tworzenia podpisu cyfrowego, który można zweryfikować przy użyciu tej techniki, zobacz Instrukcje: podpisywanie dokumentów XML przy użyciu podpisów cyfrowych.

Aby sprawdzić podpis cyfrowy dokumentu XML

  1. Aby zweryfikować dokument, należy użyć tego samego klucza asymetrycznego, który został użyty do podpisywania. CspParameters Utwórz obiekt i określ nazwę kontenera kluczy, który został użyty do podpisywania.

    CspParameters cspParams = new()
    {
        KeyContainerName = "XML_DSIG_RSA_KEY"
    };
    
    Dim cspParams As New CspParameters()
    cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
    
  2. Pobierz klucz publiczny przy użyciu RSACryptoServiceProvider klasy . Klucz jest automatycznie ładowany z kontenera kluczy według nazwy po przekazaniu CspParameters obiektu do konstruktora RSACryptoServiceProvider klasy.

    RSACryptoServiceProvider rsaKey = new(cspParams);
    
    Dim rsaKey As New RSACryptoServiceProvider(cspParams)
    
  3. XmlDocument Utwórz obiekt, ładując plik XML z dysku. Obiekt XmlDocument zawiera podpisany dokument XML do zweryfikowania.

    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. Utwórz nowy SignedXml obiekt i przekaż XmlDocument do niego obiekt.

    SignedXml signedXml = new(xmlDoc);
    
    Dim signedXml As New SignedXml(xmlDoc)
    
  5. <>signatureZnajdź element i utwórz nowy XmlNodeList obiekt.

    XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
    
    Dim nodeList As XmlNodeList = xmlDoc.GetElementsByTagName("Signature")
    
  6. Załaduj kod XML pierwszego <signature> elementu do SignedXml obiektu.

    signedXml.LoadXml((XmlElement?)nodeList[0]);
    
    signedXml.LoadXml(CType(nodeList(0), XmlElement))
    
  7. Sprawdź podpis przy użyciu CheckSignature metody i klucza publicznego RSA. Ta metoda zwraca wartość logiczną wskazującą powodzenie lub niepowodzenie.

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

Przykład

W tym przykładzie przyjęto założenie, że plik o nazwie "test.xml" istnieje w tym samym katalogu co skompilowany program. Plik "test.xml" musi być podpisany przy użyciu technik opisanych w temacie Instrukcje: podpisywanie dokumentów XML przy użyciu podpisów cyfrowych.

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

Kompilowanie kodu

Zabezpieczenia platformy .NET

Nigdy nie przechowuj ani nie przesyłaj klucza prywatnego pary kluczy asymetrycznych w postaci zwykłego tekstu. Aby uzyskać więcej informacji na temat symetrycznych i asymetrycznych kluczy kryptograficznych, zobacz Generowanie kluczy szyfrowania i odszyfrowywania.

Nigdy nie osadzaj klucza prywatnego bezpośrednio w kodzie źródłowym. Klucze osadzone można łatwo odczytać z zestawu przy użyciu Ildasm.exe (dezasembler IL) lub otwierając zestaw w edytorze tekstów, takim jak Notatnik.

Zobacz też