Gewusst wie: Verschlüsseln von XML-Elementen mit X.509-Zertifikaten

Aktualisiert: November 2007

Sie können die Klassen im System.Security.Cryptography.Xml-Namespace verwenden, um ein Element innerhalb eines XML-Dokuments zu verschlüsseln. Die XML-Verschlüsselung ist ein gängiges Verfahren zum Austauschen oder Speichern von verschlüsselten XML-Daten, mit dem der nötige Datenschutz gewährleistet wird. Weitere Informationen über den XML-Verschlüsselungsstandard finden Sie in der W3C-Spezifikation (World Wide Web Consortium) für die XML-Verschlüsselung unter http://www.w3.org/TR/xmldsig-core/ (nur auf Englisch verfügbar).

Sie verwenden die XML-Verschlüsselung u. a., um jedes XML-Element oder XML-Dokument durch ein <EncryptedData>-Element zu ersetzen, das die verschlüsselten XML-Daten enthält. Das <EncryptedData>-Element kann Unterelemente mit Informationen über die bei der Verschlüsselung verwendeten Schlüssel und Prozesse enthalten. Mit XML-Verschlüsselung kann ein Dokument nicht nur viele verschlüsselte Elemente enthalten, sondern ein Element kann auch mehrfach verschlüsselt sein. Das Codebeispiel in dieser Prozedur veranschaulicht das Erstellen eines <EncryptedData>-Elements zusammen mit weiteren Unterelementen, die Sie später bei der Entschlüsselung verwenden können.

In diesem Beispiel wird ein XML-Element mithilfe zweier Schlüssel verschlüsselt. Es wird ein X.509-Testzertifikat mithilfe von Certificate Creation-Tool (Makecert.exe) generiert und in einem Zertifikatsspeicher gespeichert. Im Beispiel wird das Zertifikat automatisch abgerufen und verwendet, um ein XML-Element mithilfe der Encrypt-Methode zu verschlüsseln. Die Encrypt-Methode erstellt intern einen separaten Sitzungsschlüssel und verwendet diesen dann zum Verschlüsseln des XML-Dokuments. Die Methode verschlüsselt den Sitzungsschlüssel und speichert ihn mit dem verschlüsselten XML-Dokument innerhalb eines neuen <EncryptedData>-Elements.

Zum Entschlüsseln des XML-Elements rufen Sie einfach die DecryptDocument-Methode auf, die aus dem Speicher automatisch das X.509-Zertifikat abruft und die notwendige Entschlüsselung vornimmt. Weitere Informationen zum Entschlüsseln eines XML-Elements, das mit dieser Prozedur verschlüsselt wurde, finden Sie unter Gewusst wie: Entschlüsseln von XML-Elementen mit X.509-Zertifikaten.

Das Beispiel eignet sich für Situationen, wenn mehrere Anwendungen verschlüsselte Daten gemeinsam nutzen müssen, oder wenn eine Anwendung verschlüsselte Daten immer dann speichern muss, wenn sie nicht ausgeführt wird.

So verschlüsseln Sie ein XML-Element mit einem X.509-Zertifikat

  1. Verwenden Sie das Certificate Creation-Tool (Makecert.exe), um ein X.509-Testzertifikat zu generieren und dem lokalen Benutzerspeicher hinzuzufügen. Sie müssen einen exportierbaren Austauschschlüssel generieren. Führen Sie den folgenden Befehl aus:

    makecert -r -pe -n "CN=XML_ENC_TEST_CERT" -b 01/01/2005 -e 01/01/2010 -sky exchange -ss my
    
  2. Erstellen Sie ein X509Store-Objekt, und initialisieren Sie dieses, um den aktuellen Benutzerspeicher zu öffnen.

    Dim store As New X509Store(StoreLocation.CurrentUser)
    
    X509Store store = new X509Store(StoreLocation.CurrentUser);
    
  3. Öffnen Sie den Speicher im schreibgeschützten Modus.

    store.Open(OpenFlags.ReadOnly)
    
    store.Open(OpenFlags.ReadOnly);
    
  4. Initialisieren Sie eine X509Certificate2Collection mit allen im Speicher enthaltenen Zertifikaten.

    Dim certCollection As X509Certificate2Collection = store.Certificates
    
    X509Certificate2Collection certCollection = store.Certificates;
    
  5. Durchlaufen Sie die Zertifikate im Speicher, und suchen Sie dasjenige mit dem entsprechenden Namen. In diesem Beispiel trägt das Zertifikat den Namen "CN=XML_ENC_TEST_CERT".

    Dim cert As X509Certificate2 = Nothing
    
    ' Loop through each certificate and find the certificate 
    ' with the appropriate name.
    Dim c As X509Certificate2
    For Each c In certCollection
        If c.Subject = "CN=XML_ENC_TEST_CERT" Then
            cert = c
    
            Exit For
        End If
    Next c
    
    X509Certificate2 cert = null;
    
    // Loop through each certificate and find the certificate 
    // with the appropriate name.
    foreach (X509Certificate2 c in certCollection)
    {
        if (c.Subject == "CN=XML_ENC_TEST_CERT")
        {
            cert = c;
    
            break;
        }
    }
    
  6. Schließen Sie den Speicher, nachdem das Zertifikat gefunden wurde.

    store.Close()
    
    store.Close();
    
  7. Erstellen Sie ein XmlDocument-Objekt, indem Sie eine XML-Datei von einem Datenträger laden. Das XmlDocument-Objekt enthält das XML-Element für die Verschlüsselung.

    Dim xmlDoc As New XmlDocument()
    
    XmlDocument xmlDoc = new XmlDocument();
    
  8. Suchen Sie das angegebene Element im XmlDocument-Objekt, und erstellen Sie ein neues XmlElement-Objekt, um das Element darzustellen, das Sie verschlüsseln möchten. In diesem Beispiel wird das "creditcard"-Element verschlüsselt.

    Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(0)
    
    
    XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
    
  9. Erstellen Sie eine neue Instanz der EncryptedXml-Klasse, und verwenden Sie sie zusammen mit dem X.059-Zertifikat zum Verschlüsseln des angegebenen Elements. Die Encrypt-Methode gibt das verschlüsselte Element als ein EncryptedData-Objekt zurück.

    Dim eXml As New EncryptedXml()
    
    ' Encrypt the element.
    Dim edElement As EncryptedData = eXml.Encrypt(elementToEncrypt, Cert)
    
    EncryptedXml eXml = new EncryptedXml();
    
    // Encrypt the element.
    EncryptedData edElement = eXml.Encrypt(elementToEncrypt, Cert);
    
  10. Ersetzen Sie das Element des ursprünglichen XmlDocument-Objekts durch das EncryptedData-Element.

    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
    
    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    
  11. Speichern Sie das XmlDocument-Objekt.

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

Beispiel

Imports System
Imports System.Xml
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates



Module Program

    Sub Main(ByVal args() As String)
        Try
            ' Create an XmlDocument object.
            Dim xmlDoc As New XmlDocument()
            ' Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load("test.xml")

            ' Open the X.509 "Current User" store in read only mode.
            Dim store As New X509Store(StoreLocation.CurrentUser)
            store.Open(OpenFlags.ReadOnly)
            ' Place all certificates in an X509Certificate2Collection object.
            Dim certCollection As X509Certificate2Collection = store.Certificates
            Dim cert As X509Certificate2 = Nothing

            ' Loop through each certificate and find the certificate 
            ' with the appropriate name.
            Dim c As X509Certificate2
            For Each c In certCollection
                If c.Subject = "CN=XML_ENC_TEST_CERT" Then
                    cert = c

                    Exit For
                End If
            Next c
            If cert Is Nothing Then
                Throw New CryptographicException("The X.509 certificate could not be found.")
            End If

            ' Close the store.
            store.Close()
            ' Encrypt the "creditcard" element.
            Encrypt(xmlDoc, "creditcard", cert)

            ' Save the XML document.
            xmlDoc.Save("test.xml")
            ' Display the encrypted XML to the console.
            Console.WriteLine("Encrypted XML:")
            Console.WriteLine()
            Console.WriteLine(xmlDoc.OuterXml)

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

    End Sub 'Main


    Sub Encrypt(ByVal Doc As XmlDocument, ByVal ElementToEncryptName As String, ByVal Cert As X509Certificate2)
        ' Check the arguments.  
        If Doc Is Nothing Then
            Throw New ArgumentNullException("Doc")
        End If
        If ElementToEncryptName Is Nothing Then
            Throw New ArgumentNullException("ElementToEncrypt")
        End If
        If Cert Is Nothing Then
            Throw New ArgumentNullException("Cert")
        End If
        ''''''''''''''''''''''''''''''''''''''''''''''''
        ' Find the specified element in the XmlDocument
        ' object and create a new XmlElemnt object.
        ''''''''''''''''''''''''''''''''''''''''''''''''
        Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(0)

        ' Throw an XmlException if the element was not found.
        If elementToEncrypt Is Nothing Then
            Throw New XmlException("The specified element was not found")
        End If

        ''''''''''''''''''''''''''''''''''''''''''''''''
        ' Create a new instance of the EncryptedXml class 
        ' and use it to encrypt the XmlElement with the 
        ' X.509 Certificate.
        ''''''''''''''''''''''''''''''''''''''''''''''''
        Dim eXml As New EncryptedXml()

        ' Encrypt the element.
        Dim edElement As EncryptedData = eXml.Encrypt(elementToEncrypt, Cert)
        ''''''''''''''''''''''''''''''''''''''''''''''''
        ' Replace the element from the original XmlDocument
        ' object with the EncryptedData element.
        ''''''''''''''''''''''''''''''''''''''''''''''''
        EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
    End Sub
End Module
using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            // Create an XmlDocument object.
            XmlDocument xmlDoc = new XmlDocument();

            // Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load("test.xml");

            // Open the X.509 "Current User" store in read only mode.
            X509Store store = new X509Store(StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);

            // Place all certificates in an X509Certificate2Collection object.
            X509Certificate2Collection certCollection = store.Certificates;

            X509Certificate2 cert = null;

            // Loop through each certificate and find the certificate 
            // with the appropriate name.
            foreach (X509Certificate2 c in certCollection)
            {
                if (c.Subject == "CN=XML_ENC_TEST_CERT")
                {
                    cert = c;

                    break;
                }
            }

            if (cert == null)
            {
                throw new CryptographicException("The X.509 certificate could not be found.");
            }

            // Close the store.
            store.Close();

            // Encrypt the "creditcard" element.
            Encrypt(xmlDoc, "creditcard", cert);

            // Save the XML document.
            xmlDoc.Save("test.xml");

            // Display the encrypted XML to the console.
            Console.WriteLine("Encrypted XML:");
            Console.WriteLine();
            Console.WriteLine(xmlDoc.OuterXml);

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

    }

    public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, X509Certificate2 Cert)
    {
        // Check the arguments.  
        if (Doc == null)
            throw new ArgumentNullException("Doc");
        if (ElementToEncrypt == null)
            throw new ArgumentNullException("ElementToEncrypt");
        if (Cert == null)
            throw new ArgumentNullException("Cert");

        ////////////////////////////////////////////////
        // Find the specified element in the XmlDocument
        // object and create a new XmlElemnt object.
        ////////////////////////////////////////////////

        XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
        // Throw an XmlException if the element was not found.
        if (elementToEncrypt == null)
        {
            throw new XmlException("The specified element was not found");

        }

        //////////////////////////////////////////////////
        // Create a new instance of the EncryptedXml class 
        // and use it to encrypt the XmlElement with the 
        // X.509 Certificate.
        //////////////////////////////////////////////////

        EncryptedXml eXml = new EncryptedXml();

        // Encrypt the element.
        EncryptedData edElement = eXml.Encrypt(elementToEncrypt, Cert);

        ////////////////////////////////////////////////////
        // Replace the element from the original XmlDocument
        // object with the EncryptedData element.
        ////////////////////////////////////////////////////
        EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    }
}

Dieses Beispiel setzt voraus, dass eine Datei mit dem Namen "test.xml" im gleichen Verzeichnis wie das kompilierte Programm vorhanden ist. Vorausgesetzt wird auch, dass "test.xml" ein "creditcard"-Element enthält. Sie können die folgende XML in eine Datei mit dem Namen test.xml einfügen und mit diesem Beispiel verwenden.

<root>
    <creditcard>
        <number>19834209</number>
        <expiry>02/02/2002</expiry>
    </creditcard>
</root>

Kompilieren des Codes

Sicherheit

Das in diesem Beispiel verwendete X.509-Zertifikat ist nur für Testzwecke vorgesehen. Anwendungen sollten ein X.059-Zertifikat verwenden, das entweder von einer vertrauenswürdigen Zertifizierungsstelle oder vom Microsoft Windows-Zertifikatsserver generiert wurde.

Siehe auch

Aufgaben

Gewusst wie: Entschlüsseln von XML-Elementen mit X.509-Zertifikaten

Referenz

System.Security.Cryptography.Xml

Weitere Ressourcen

XML-Verschlüsselung und digitale Signaturen