Condividi tramite


Procedura: crittografare gli elementi XML con certificati X.509

Aggiornamento: novembre 2007

È possibile utilizzare le classi dello spazio dei nomi System.Security.Cryptography.Xml per crittografare un elemento all'interno di un documento XML. La crittografia XML è un sistema standard per lo scambio o la memorizzazione di dati XML crittografati che garantisce un'adeguata protezione da letture non autorizzate. Per ulteriori informazioni sulla crittografia XML, vedere la specifica W3C (World Wide Web Consortium) relativa a questo standard all'indirizzo http://www.w3.org/TR/xmldsig-core/ (informazioni in lingua inglese).

È possibile utilizzare la crittografia XML per sostituire qualsiasi elemento o documento XML con un elemento <EncryptedData> contenente i dati XML crittografati. L'elemento <EncryptedData> può contenere sottoelementi che includono informazioni sulle chiavi e i processi utilizzati durante la crittografia. La crittografia XML consente di inserire più elementi crittografati all'interno di un documento e di crittografare un elemento più volte. Nell'esempio di codice relativo a questa procedura viene illustrato come creare un elemento <EncryptedData> insieme a diversi altri sottoelementi utilizzabili in un secondo momento durante la decrittografia.

Nell'esempio un elemento XML viene crittografato mediante due chiavi. Un certificato X.509 di prova viene generato mediante lo Strumento di creazione certificati (Makecert.exe) e quindi salvato in un archivio certificati. Successivamente, viene recuperato a livello di codice e utilizzato per crittografare un elemento XML attraverso il metodo Encrypt. Tale metodo crea internamente una chiave di sessione separata e la utilizza per crittografare il documento XML. La chiave di sessione viene crittografata e salvata insieme ai dati XML crittografati all'interno di un nuovo elemento <EncryptedData>.

Per decrittografare l'elemento XML, è sufficiente chiamare il metodo DecryptDocument, che recupera automaticamente il certificato X.509 dall'archivio ed esegue la decrittografia necessaria. Per ulteriori informazioni su come decrittografare un elemento XML crittografato mediante questa procedura, vedere Procedura: decrittografare gli elementi XML con certificati X.509.

Questo esempio si riferisce alle situazioni in cui più applicazioni devono condividere dati crittografati o un'applicazione deve salvare i dati crittografati tra un'esecuzione e l'altra.

Per crittografare un elemento XML con un certificato X.509

  1. Utilizzare lo Strumento di creazione certificati (Makecert.exe) per generare un certificato X.509 di prova e inserirlo nell'archivio utente locale. È necessario generare una chiave di scambio e renderla esportabile. Eseguire il comando seguente:

    makecert -r -pe -n "CN=XML_ENC_TEST_CERT" -b 01/01/2005 -e 01/01/2010 -sky exchange -ss my
    
  2. Creare un oggetto X509Store e inizializzarlo per aprire l'archivio utente corrente.

    Dim store As New X509Store(StoreLocation.CurrentUser)
    
    X509Store store = new X509Store(StoreLocation.CurrentUser);
    
  3. Aprire l'archivio in modalità di sola lettura.

    store.Open(OpenFlags.ReadOnly)
    
    store.Open(OpenFlags.ReadOnly);
    
  4. Inizializzare un X509Certificate2Collection con tutti i certificati contenuti nell'archivio.

    Dim certCollection As X509Certificate2Collection = store.Certificates
    
    X509Certificate2Collection certCollection = store.Certificates;
    
  5. Scorrere i certificati nell'archivio e trovare quello con il nome appropriato. In questo esempio il certificato è denominato "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. Chiudere l'archivio dopo aver individuato il certificato.

    store.Close()
    
    store.Close();
    
  7. Creare un oggetto XmlDocument caricando un file XML dal disco. L'oggetto XmlDocument contiene l'elemento XML da crittografare.

    Dim xmlDoc As New XmlDocument()
    
    XmlDocument xmlDoc = new XmlDocument();
    
  8. Trovare l'elemento specificato nell'oggetto XmlDocument e creare un nuovo oggetto XmlElement per rappresentare l'elemento da crittografare. In questo esempio viene crittografato l'elemento "creditcard".

    Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(0)
    
    
    XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
    
  9. Creare una nuova istanza della classe EncryptedXml e utilizzarla per crittografare l'elemento specificato mediante il certificato X.509. Il metodo Encrypt restituisce l'elemento crittografato come un oggetto EncryptedData.

    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. Sostituire l'elemento dell'oggetto XmlDocument originale con l'elemento EncryptedData.

    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
    
    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    
  11. Salvare l'oggetto XmlDocument.

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

Esempio

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);
    }
}

In questo esempio si presuppone che un file denominato "test.xml" si trovi nella stessa directory del programma compilato e che contenga un elemento "creditcard". È possibile inserire i dati XML riportati di seguito in un file denominato test.xml e utilizzarlo con questo esempio.

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

Compilazione del codice

Sicurezza

Il certificato X.509 utilizzato in questo esempio è valido solo a scopo di testing. Le applicazioni devono utilizzare un certificato X.509 generato da un'autorità di certificazione attendibile o un certificato generato da Microsoft Windows Certificate Server.

Vedere anche

Attività

Procedura: decrittografare gli elementi XML con certificati X.509

Riferimenti

System.Security.Cryptography.Xml

Altre risorse

Crittografia XML e firme digitali