Partager via


Comment : chiffrer des éléments XML avec des clés asymétriques

Mise à jour : novembre 2007

Vous pouvez utiliser les classes dans l'espace de noms System.Security.Cryptography.Xml pour chiffrer un élément dans un document XML. Le chiffrement XML est une façon standard d'échanger ou de stocker des données XML chiffrées, sans risque que les données soient lues facilement. Pour plus d'informations sur les normes de chiffrement XML, consultez la spécification de chiffrement du World Wide Web Consortium (W3C) à l'adresse http://www.w3.org/TR/xmldsig-core/.

Vous pouvez utiliser le chiffrement XML pour remplacer tout élément ou document XML par un élément <EncryptedData> qui contient les données XML chiffrées. L'élément <EncryptedData> peut également contenir des sous-éléments qui incluent des informations sur les clés et processus utilisés pendant le chiffrement. Le chiffrement XML autorise un document à contenir plusieurs éléments chiffrés et autorise un élément à être chiffré plusieurs fois. L'exemple de code dans cette procédure vous indique comment créer un élément <EncryptedData> avec plusieurs autres sous-éléments que vous pouvez utiliser ultérieurement pendant le déchiffrement.

Cet exemple chiffre un élément XML à l'aide de deux clés. Il génère une paire de clés publique/privée RSA et enregistre la paire de clés dans un conteneur de clé sécurisé. L'exemple crée ensuite une clé de session séparée à l'aide de l'algorithme Advanced Encryption Standard (AES), également appelé algorithme de Rijndael. L'exemple utilise la clé de session AES pour chiffrer le document XML, puis utilise la clé publique RSA pour chiffrer la clé de session AES. Enfin, l'exemple enregistre la clé de session AES chiffrée et les données XML chiffrées dans le document XML dans un nouvel élément <EncryptedData>.

Pour déchiffrer l'élément XML, récupérez la clé privée RSA du conteneur de clé, utilisez-la pour déchiffrer la clé de session, puis utilisez la clé de session pour déchiffrer le document. Pour plus d'informations sur le déchiffrement d'un élément XML chiffré à l'aide de cette procédure, consultez Comment : déchiffrer des éléments XML avec des clés asymétriques.

Cet exemple est approprié lorsque plusieurs applications doivent partager les données chiffrées ou lorsqu'une application doit enregistrer les données chiffrées entre chacune de ses exécutions.

Pour chiffrer un élément XML avec une clé asymétrique

  1. Créez un objet CspParameters et spécifiez le nom du conteneur de clé.

    Dim cspParams As New CspParameters()
    cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
    
         CspParameters cspParams = new CspParameters();
            cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
    
  2. Générez une clé symétrique à l'aide de la classe RSACryptoServiceProvider. La clé est enregistrée automatiquement sur le conteneur de clé lorsque vous passez l'objet CspParameters au constructeur de la classe RSACryptoServiceProvider. Cette clé sera utilisée pour chiffrer la clé de session AES et peut être récupérée ultérieurement pour la déchiffrer.

    Dim rsaKey As New RSACryptoServiceProvider(cspParams)
    
         RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
    
  3. Créez un objet XmlDocument en chargeant un fichier XML à partir du disque. L'objet XmlDocument contient l'élément XML à chiffrer.

    ' Create an XmlDocument object.
    Dim xmlDoc As New XmlDocument()
    
    ' Load an XML file into the XmlDocument object.
    Try
        xmlDoc.PreserveWhitespace = True
        xmlDoc.Load("test.xml")
    Catch e As Exception
        Console.WriteLine(e.Message)
    End Try
    
         // Create an XmlDocument object.
            XmlDocument xmlDoc = new XmlDocument();
    
            // Load an XML file into the XmlDocument object.
            try
            {
                xmlDoc.PreserveWhitespace = true;
                xmlDoc.Load("test.xml");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
    
  4. Recherchez l'élément spécifié dans l'objet XmlDocument et créez un nouvel objet XmlElement pour représenter l'élément que vous souhaitez chiffrer. Dans cet exemple, l'élément "creditcard" est chiffré.

    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
    
         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");
    
            }
    
  5. Créez une clé de session à l'aide de la classe RijndaelManaged. Cette clé chiffrera l'élément XML, et sera ensuite chiffrée et placée dans le document XML.

    ' Create a 256 bit Rijndael key.
    sessionKey = New RijndaelManaged()
    sessionKey.KeySize = 256
    
             // Create a 256 bit Rijndael key.
                sessionKey = new RijndaelManaged();
                sessionKey.KeySize = 256;
    
  6. Créez une instance de la classe EncryptedXml et utilisez-la pour chiffrer l'élément spécifié à l'aide de la clé de session. La méthode EncryptData retourne l'élément chiffré sous la forme d'un tableau d'octets chiffrés.

    Dim eXml As New EncryptedXml()
    
    Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, sessionKey, False)
    
             EncryptedXml eXml = new EncryptedXml();
    
                byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);
    
  7. Construisez un objet EncryptedData et remplissez-le avec l'identificateur d'URL de l'élément XML chiffré. Cet identificateur d'URL fait savoir à une partie de chiffrement que le XML contient un élément chiffré. Vous pouvez utiliser le champ XmlEncElementUrl pour spécifier l'identificateur d'URL. L'élément XML de texte brut sera remplacé par un élément <EncrypotedData> encapsulé par cet objet EncryptedData.

    Dim edElement As New EncryptedData()
    edElement.Type = EncryptedXml.XmlEncElementUrl
    edElement.Id = EncryptionElementID
    
             EncryptedData edElement = new EncryptedData();
                edElement.Type = EncryptedXml.XmlEncElementUrl;
                edElement.Id = EncryptionElementID;
    
  8. Créez un objet EncryptionMethod qui est initialisé à l'identificateur d'URL de l'algorithme de chiffrement utilisé pour générer la clé de session. Passez l'objet EncryptionMethod à la propriété EncryptionMethod.

    edElement.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncAES256Url)
    
             edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
    
  9. Créez un objet EncryptedKey pour contenir la clé de session chiffrée. Chiffrez la clé de session, ajoutez-la à l'objet EncryptedKey et entrez un nom de clé de session ainsi qu'une URL d'identificateur de clé.

    Dim ek As New EncryptedKey()
    
    Dim encryptedKey As Byte() = EncryptedXml.EncryptKey(sessionKey.Key, Alg, False)
    
    ek.CipherData = New CipherData(encryptedKey)
    
    ek.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncRSA15Url)
    
             EncryptedKey ek = new EncryptedKey();
    
                byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, Alg, false);
    
                ek.CipherData = new CipherData(encryptedKey);
    
                ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);
    
  10. Créez un objet DataReference qui mappe les données chiffrées à une clé de session particulière. Cette étape facultative vous permet de spécifier facilement que plusieurs parties d'un document XML ont été chiffrées par une seule clé.

    Dim dRef As New DataReference()
    
    ' Specify the EncryptedData URI. 
    dRef.Uri = "#" + EncryptionElementID
    
    ' Add the DataReference to the EncryptedKey.
    ek.AddReference(dRef)
    
             DataReference dRef = new DataReference();
    
                // Specify the EncryptedData URI.
                dRef.Uri = "#" + EncryptionElementID;
    
                // Add the DataReference to the EncryptedKey.
                ek.AddReference(dRef);
    
  11. Ajoutez la clé chiffrée à l'objet EncryptedData.

    edElement.KeyInfo.AddClause(New KeyInfoEncryptedKey(ek))
    
             edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
    
  12. Créez un objet KeyInfo pour spécifier le nom de la clé RSA. Ajoutez-le à l'objet EncryptedData. Cela permet à la partie de déchiffrement d'identifier la clé asymétrique correcte à utiliser lors du déchiffrement de la clé de session.

    ' Create a new KeyInfo element.
    edElement.KeyInfo = New KeyInfo()
    
    ' Create a new KeyInfoName element.
    Dim kin As New KeyInfoName()
    
    ' Specify a name for the key.
    kin.Value = KeyName
    
    ' Add the KeyInfoName element to the 
    ' EncryptedKey object.
    ek.KeyInfo.AddClause(kin)
    
             // Create a new KeyInfo element.
                edElement.KeyInfo = new KeyInfo();
    
                // Create a new KeyInfoName element.
                KeyInfoName kin = new KeyInfoName();
    
                // Specify a name for the key.
                kin.Value = KeyName;
    
                // Add the KeyInfoName element to the
                // EncryptedKey object.
                ek.KeyInfo.AddClause(kin);
    
  13. Ajoutez les données d'élément chiffrées à l'objet EncryptedData.

    edElement.CipherData.CipherValue = encryptedElement
    
             edElement.CipherData.CipherValue = encryptedElement;
    
  14. Remplacez l'élément de l'objet XmlDocument d'origine par l'élément EncryptedData.

    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
    
             EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    
  15. Enregistrez l'objet XmlDocument.

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

Exemple

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



Module Program

    Sub Main(ByVal args() As String)
        ' Create an XmlDocument object.
        Dim xmlDoc As New XmlDocument()

        ' Load an XML file into the XmlDocument object.
        Try
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load("test.xml")
        Catch e As Exception
            Console.WriteLine(e.Message)
        End Try
        ' Create a new CspParameters object to specify
        ' a key container.
        Dim cspParams As New CspParameters()
        cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
        ' Create a new RSA key and save it in the container.  This key will encrypt 
        ' a symmetric key, which will then be encryped in the XML document.
        Dim rsaKey As New RSACryptoServiceProvider(cspParams)
        Try
            ' Encrypt the "creditcard" element.
            Encrypt(xmlDoc, "creditcard", "EncryptedElement1", rsaKey, "rsaKey")


            ' 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)
        Finally
            ' Clear the RSA key.
            rsaKey.Clear()
        End Try


        Console.ReadLine()

    End Sub


    Sub Encrypt(ByVal Doc As XmlDocument, ByVal ElementToEncryptName As String, ByVal EncryptionElementID As String, ByVal Alg As RSA, ByVal KeyName As String)
        ' 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 EncryptionElementID Is Nothing Then
            Throw New ArgumentNullException("EncryptionElementID")
        End If
        If Alg Is Nothing Then
            Throw New ArgumentNullException("Alg")
        End If
        If KeyName Is Nothing Then
            Throw New ArgumentNullException("KeyName")
        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
        Dim sessionKey As RijndaelManaged = Nothing

        Try
            ''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Create a new instance of the EncryptedXml class 
            ' and use it to encrypt the XmlElement with the 
            ' a new random symmetric key.
            ''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Create a 256 bit Rijndael key.
            sessionKey = New RijndaelManaged()
            sessionKey.KeySize = 256
            Dim eXml As New EncryptedXml()

            Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, sessionKey, False)
            ''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Construct an EncryptedData object and populate
            ' it with the desired encryption information.
            ''''''''''''''''''''''''''''''''''''''''''''''''''
            Dim edElement As New EncryptedData()
            edElement.Type = EncryptedXml.XmlEncElementUrl
            edElement.Id = EncryptionElementID
            ' Create an EncryptionMethod element so that the 
            ' receiver knows which algorithm to use for decryption.
            edElement.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncAES256Url)
            ' Encrypt the session key and add it to an EncryptedKey element.
            Dim ek As New EncryptedKey()

            Dim encryptedKey As Byte() = EncryptedXml.EncryptKey(sessionKey.Key, Alg, False)

            ek.CipherData = New CipherData(encryptedKey)

            ek.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncRSA15Url)
            ' Create a new DataReference element
            ' for the KeyInfo element.  This optional
            ' element specifies which EncryptedData 
            ' uses this key.  An XML document can have
            ' multiple EncryptedData elements that use
            ' different keys.
            Dim dRef As New DataReference()

            ' Specify the EncryptedData URI. 
            dRef.Uri = "#" + EncryptionElementID

            ' Add the DataReference to the EncryptedKey.
            ek.AddReference(dRef)
            ' Add the encrypted key to the 
            ' EncryptedData object.
            edElement.KeyInfo.AddClause(New KeyInfoEncryptedKey(ek))
            ' Set the KeyInfo element to specify the
            ' name of the RSA key.
            ' Create a new KeyInfo element.
            edElement.KeyInfo = New KeyInfo()

            ' Create a new KeyInfoName element.
            Dim kin As New KeyInfoName()

            ' Specify a name for the key.
            kin.Value = KeyName

            ' Add the KeyInfoName element to the 
            ' EncryptedKey object.
            ek.KeyInfo.AddClause(kin)
            ' Add the encrypted element data to the 
            ' EncryptedData object.
            edElement.CipherData.CipherValue = encryptedElement
            ''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Replace the element from the original XmlDocument
            ' object with the EncryptedData element.
            ''''''''''''''''''''''''''''''''''''''''''''''''''
            EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
        Catch e As Exception
            ' re-throw the exception.
            Throw e
        Finally
            If Not (sessionKey Is Nothing) Then
                sessionKey.Clear()
            End If
        End Try

    End Sub
End Module
using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;

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

        // Load an XML file into the XmlDocument object.
        try
        {
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load("test.xml");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        // Create a new CspParameters object to specify
        // a key container.
        CspParameters cspParams = new CspParameters();
        cspParams.KeyContainerName = "XML_ENC_RSA_KEY";

        // Create a new RSA key and save it in the container.  This key will encrypt
        // a symmetric key, which will then be encryped in the XML document.
        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

        try
        {
            // Encrypt the "creditcard" element.
            Encrypt(xmlDoc, "creditcard", "EncryptedElement1", rsaKey, "rsaKey");


            // 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);
        }
        finally
        {
            // Clear the RSA key.
            rsaKey.Clear();
        }


        Console.ReadLine();
    }

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

        ////////////////////////////////////////////////
        // 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");

        }
        RijndaelManaged sessionKey = null;

        try
        {
            //////////////////////////////////////////////////
            // Create a new instance of the EncryptedXml class
            // and use it to encrypt the XmlElement with the
            // a new random symmetric key.
            //////////////////////////////////////////////////

            // Create a 256 bit Rijndael key.
            sessionKey = new RijndaelManaged();
            sessionKey.KeySize = 256;

            EncryptedXml eXml = new EncryptedXml();

            byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);
            ////////////////////////////////////////////////
            // Construct an EncryptedData object and populate
            // it with the desired encryption information.
            ////////////////////////////////////////////////

            EncryptedData edElement = new EncryptedData();
            edElement.Type = EncryptedXml.XmlEncElementUrl;
            edElement.Id = EncryptionElementID;
            // Create an EncryptionMethod element so that the
            // receiver knows which algorithm to use for decryption.

            edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
            // Encrypt the session key and add it to an EncryptedKey element.
            EncryptedKey ek = new EncryptedKey();

            byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, Alg, false);

            ek.CipherData = new CipherData(encryptedKey);

            ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);

            // Create a new DataReference element
            // for the KeyInfo element.  This optional
            // element specifies which EncryptedData
            // uses this key.  An XML document can have
            // multiple EncryptedData elements that use
            // different keys.
            DataReference dRef = new DataReference();

            // Specify the EncryptedData URI.
            dRef.Uri = "#" + EncryptionElementID;

            // Add the DataReference to the EncryptedKey.
            ek.AddReference(dRef);
            // Add the encrypted key to the
            // EncryptedData object.

            edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
            // Set the KeyInfo element to specify the
            // name of the RSA key.

            // Create a new KeyInfo element.
            edElement.KeyInfo = new KeyInfo();

            // Create a new KeyInfoName element.
            KeyInfoName kin = new KeyInfoName();

            // Specify a name for the key.
            kin.Value = KeyName;

            // Add the KeyInfoName element to the
            // EncryptedKey object.
            ek.KeyInfo.AddClause(kin);
            // Add the encrypted element data to the
            // EncryptedData object.
            edElement.CipherData.CipherValue = encryptedElement;
            ////////////////////////////////////////////////////
            // Replace the element from the original XmlDocument
            // object with the EncryptedData element.
            ////////////////////////////////////////////////////
            EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
        }
        catch(Exception e)
        {
            // re-throw the exception.
            throw e;
        }
        finally
        {
            if (sessionKey != null)
            {
                sessionKey.Clear();
            }

        }

    }

}

Cet exemple suppose qu'un fichier nommé "test.xml" existe dans le même répertoire que le programme compilé. Il suppose également que "test.xml" contient un élément "creditcard". Vous pouvez placer le XML suivant dans un fichier appelé test.xml et l'utiliser avec cet exemple.

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

Compilation du code

Sécurité

Vous ne devez jamais stocker une clé de chiffrement symétrique en texte brut ou transférer une clé symétrique entre des ordinateurs en texte brut. De plus, vous ne devez jamais stocker ou transférer la clé privée d'une paire de clés asymétrique en texte brut. Pour plus d'informations sur les clés de chiffrement symétriques et asymétriques, consultez Génération de clés pour le chiffrement et le déchiffrement.

N'incorporez jamais directement une clé dans votre code source. Les clés incorporées peuvent être lues facilement à partir d'un assembly à l'aide du MSIL Disassembler (Ildasm.exe) ou en ouvrant l'assembly dans un éditeur de texte tel que le Bloc-notes.

Lorsque vous avez fini d'utiliser une clé de chiffrement, effacez-la de la mémoire en affectant la valeur zéro à chaque octet ou en appelant la méthode Clear de la classe de chiffrement managée. Les clés de chiffrement peuvent parfois être lues à partir de la mémoire par un débogueur ou peuvent être lues à partir d'un disque dur si l'emplacement de mémoire est paginé sur le disque.

Voir aussi

Tâches

Comment : déchiffrer des éléments XML avec des clés asymétriques

Référence

System.Security.Cryptography.Xml

Autres ressources

Chiffrement XML et signatures numériques