Porady: podpisywanie dokumentów XML za pomocą podpisów cyfrowych

Klasy w System.Security.Cryptography.Xml przestrzeni nazw umożliwiają podpisywanie dokumentu XML lub części dokumentu XML 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 zalecenia World Wide Web Consortium (W3C) Składnia i przetwarzanie podpisu XML.

Uwaga

Kod w tym artykule dotyczy systemu Windows.

Przykład kodu w tej procedurze pokazuje, jak cyfrowo podpisać cały dokument XML i dołączyć podpis do dokumentu w elemecie <Signature> . Przykład tworzy klucz podpisywania RSA, dodaje klucz do bezpiecznego kontenera kluczy, a następnie używa klucza do cyfrowego podpisywania dokumentu XML. Klucz można następnie pobrać, aby zweryfikować podpis cyfrowy XML lub użyć go do podpisania innego dokumentu XML.

Aby uzyskać informacje o sposobie weryfikowania podpisu cyfrowego XML utworzonego przy użyciu tej procedury, zobacz Instrukcje: Weryfikowanie podpisów cyfrowych dokumentów XML.

Aby cyfrowo podpisać dokument XML

  1. CspParameters Utwórz obiekt i określ nazwę kontenera kluczy.

    CspParameters cspParams = new()
    {
        KeyContainerName = "XML_DSIG_RSA_KEY"
    };
    
    Dim cspParams As New CspParameters With {
        .KeyContainerName = "XML_DSIG_RSA_KEY"
    }
    
  2. Generowanie klucza asymetrycznego RSACryptoServiceProvider przy użyciu klasy . Klucz jest automatycznie zapisywany w kontenerze kluczy podczas przekazywania CspParameters obiektu do konstruktora RSACryptoServiceProvider klasy. Ten klucz będzie używany do podpisywania dokumentu XML.

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

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

    SignedXml signedXml = new(xmlDoc)
    {
    
    Dim signedXml As New SignedXml(xmlDoc)
    
  5. Dodaj klucz RSA podpisywania SignedXml do obiektu .

        SigningKey = rsaKey
    };
    
    signedXml.SigningKey = rsaKey
    
  6. Utwórz obiekt opisujący Reference , co należy podpisać. Aby podpisać cały dokument, ustaw Uri właściwość na "".

    // Create a reference to be signed.
    Reference reference = new()
    {
        Uri = ""
    };
    
    ' Create a reference to be signed.
    Dim reference As New Reference()
    reference.Uri = ""
    
  7. XmlDsigEnvelopedSignatureTransform Dodaj obiekt do Reference obiektu. Przekształcenie umożliwia weryfikatorowi reprezentowanie danych XML w identyczny sposób, w jaki użyto elementu podpisującego. Dane XML mogą być reprezentowane na różne sposoby, więc ten krok jest niezbędny do weryfikacji.

    XmlDsigEnvelopedSignatureTransform env = new();
    reference.AddTransform(env);
    
    Dim env As New XmlDsigEnvelopedSignatureTransform()
    reference.AddTransform(env)
    
  8. Reference Dodaj obiekt do SignedXml obiektu.

    signedXml.AddReference(reference);
    
    signedXml.AddReference(reference)
    
  9. Oblicz podpis, wywołując metodę ComputeSignature .

    signedXml.ComputeSignature();
    
    signedXml.ComputeSignature()
    
  10. Pobierz reprezentację XML podpisu ( <Signature> elementu) i zapisz go w nowym XmlElement obiekcie.

    XmlElement xmlDigitalSignature = signedXml.GetXml();
    
    Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
    
  11. Dołącz element do XmlDocument obiektu.

    xmlDoc.DocumentElement?.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
    
    xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, True))
    
  12. Zapisz dokument.

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

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. Poniższy kod XML można umieścić w pliku o nazwie test.xml i użyć go w tym przykładzie.

<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

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ż