Partager via


Comment : utiliser la protection des données

Mise à jour : novembre 2007

Le .NET Framework fournit l'accès à l'API de protection des données (DPAPI), qui vous permet de chiffrer des données à l'aide d'informations du compte d'utilisateur ou de l'ordinateur actuel. Lorsque vous utilisez la DPAPI, vous allégez la difficulté de générer et de stocker explicitement une clé de chiffrement.

Utilisez la classe ProtectedMemory pour chiffrer un tableau d'octets en mémoire. Cette fonctionnalité est disponible dans Microsoft Windows XP et les systèmes d'exploitation ultérieurs. Vous pouvez spécifier que la mémoire chiffrée par le processus actuel peut être déchiffrée par le processus actuel uniquement, par tous les processus, ou par le même contexte utilisateur. Consultez l'énumération MemoryProtectionScope pour une description détaillée des options ProtectedMemory.

Utilisez la classe ProtectedData pour chiffrer une copie d'un tableau d'octets. Cette fonctionnalité est disponible dans Microsoft Windows 2000 et les systèmes d'exploitation ultérieurs. Vous pouvez spécifier que les données chiffrées par le compte d'utilisateur actuel peuvent être déchiffrées par le même compte d'utilisateur uniquement, ou spécifier que les données chiffrées par le compte d'utilisateur actuel peuvent être déchiffrées par n'importe quel compte sur l'ordinateur. Consultez l'énumération DataProtectionScope pour une description détaillée des options ProtectedData.

Pour chiffrer les données en mémoire à l'aide de la protection des données

  • Appelez la méthode Protect statique en passant un tableau d'octets à chiffrer, l'entropie, et la portée de protection de la mémoire.

Pour déchiffrer les données en mémoire à l'aide de la protection des données

  • Appelez la méthode Unprotect statique en passant un tableau d'octets à déchiffrer et la portée de protection de la mémoire.

Pour chiffrer des données dans un fichier ou un flux à l'aide de la protection des données

  1. Créez une entropie aléatoire.

  2. Appelez la méthode Protect statique en passant un tableau d'octets à chiffrer, l'entropie, et la portée de protection des données.

  3. Écrivez les données chiffrées dans un fichier ou un flux de données.

Pour déchiffrer des données depuis un fichier ou un flux à l'aide de la protection des données

  1. Lisez les données chiffrées depuis un fichier ou un flux de données.

  2. Appelez la méthode Unprotect statique en passant un tableau d'octets à déchiffrer et la portée de protection des données.

Exemple

L'exemple de code suivant montre deux formes de chiffrement et de déchiffrement. D'abord, l'exemple de code chiffre puis déchiffre un tableau d'octets en mémoire. L'exemple de code chiffre ensuite une copie d'un tableau d'octets, l'enregistre dans un fichier, charge à nouveau les données à partir du fichier, puis déchiffre les données. L'exemple affiche les données d'origine, les données chiffrées et les données déchiffrées.

Imports System
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography



Public Module MemoryProtectionSample

    Sub Main()
        Run()

    End Sub 'Main


    Sub Run()
        Try

            ''''''''''''''''''''''''''''''''''''
            '
            ' Memory Encryption - ProtectedMemory
            '
            ''''''''''''''''''''''''''''''''''''
            ' Create the original data to be encrypted (The data length should be a multiple of 16).
            Dim toEncrypt As Byte() = UnicodeEncoding.ASCII.GetBytes("ThisIsSomeData16")

            Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(toEncrypt))
            Console.WriteLine("Encrypting...")

            ' Encrypt the data in memory.
            EncryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon)

            Console.WriteLine("Encrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt))
            Console.WriteLine("Decrypting...")

            ' Decrypt the data in memory.
            DecryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon)

            Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt))


            ''''''''''''''''''''''''''''''''''''
            '
            ' Data Encryption - ProtectedData
            '
            ''''''''''''''''''''''''''''''''''''
            ' Create the original data to be encrypted
            toEncrypt = UnicodeEncoding.ASCII.GetBytes("This is some data of any length.")

            ' Create a file.
            Dim fStream As New FileStream("Data.dat", FileMode.OpenOrCreate)

            ' Create some random entropy.
            Dim entropy As Byte() = CreateRandomEntropy()

            Console.WriteLine()
            Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(toEncrypt))
            Console.WriteLine("Encrypting and writing to disk...")

            ' Encrypt a copy of the data to the stream.
            Dim bytesWritten As Integer = EncryptDataToStream(toEncrypt, entropy, DataProtectionScope.CurrentUser, fStream)

            fStream.Close()

            Console.WriteLine("Reading data from disk and decrypting...")

            ' Open the file.
            fStream = New FileStream("Data.dat", FileMode.Open)

            ' Read from the stream and decrypt the data.
            Dim decryptData As Byte() = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, bytesWritten)

            fStream.Close()

            Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(decryptData))


        Catch e As Exception
            Console.WriteLine("ERROR: " + e.Message)
        End Try

    End Sub 'Run



    Sub EncryptInMemoryData(ByVal Buffer() As Byte, ByVal Scope As MemoryProtectionScope)
        If Buffer.Length <= 0 Then
            Throw New ArgumentException("Buffer")
        End If
        If Buffer Is Nothing Then
            Throw New ArgumentNullException("Buffer")
        End If

        ' Encrypt the data in memory. The result is stored in the same same array as the original data.
        ProtectedMemory.Protect(Buffer, Scope)

    End Sub 'EncryptInMemoryData


    Sub DecryptInMemoryData(ByVal Buffer() As Byte, ByVal Scope As MemoryProtectionScope)
        If Buffer.Length <= 0 Then
            Throw New ArgumentException("Buffer")
        End If
        If Buffer Is Nothing Then
            Throw New ArgumentNullException("Buffer")
        End If

        ' Decrypt the data in memory. The result is stored in the same same array as the original data.
        ProtectedMemory.Unprotect(Buffer, Scope)

    End Sub 'DecryptInMemoryData


    Function CreateRandomEntropy() As Byte()
        ' Create a byte array to hold the random value.
        Dim entropy(15) As Byte

        ' Create a new instance of the RNGCryptoServiceProvider.
        ' Fill the array with a random value.
        Dim RNG As New RNGCryptoServiceProvider()

        RNG.GetBytes(entropy)

        ' Return the array.
        Return entropy

    End Function 'CreateRandomEntropy



    Function EncryptDataToStream(ByVal Buffer() As Byte, ByVal Entropy() As Byte, ByVal Scope As DataProtectionScope, ByVal S As Stream) As Integer
        If Buffer.Length <= 0 Then
            Throw New ArgumentException("Buffer")
        End If
        If Buffer Is Nothing Then
            Throw New ArgumentNullException("Buffer")
        End If
        If Entropy.Length <= 0 Then
            Throw New ArgumentException("Entropy")
        End If
        If Entropy Is Nothing Then
            Throw New ArgumentNullException("Entropy")
        End If
        If S Is Nothing Then
            Throw New ArgumentNullException("S")
        End If
        Dim length As Integer = 0

        ' Encrypt the data in memory. The result is stored in the same same array as the original data.
        Dim encrptedData As Byte() = ProtectedData.Protect(Buffer, Entropy, Scope)

        ' Write the encrypted data to a stream.
        If S.CanWrite AndAlso Not (encrptedData Is Nothing) Then
            S.Write(encrptedData, 0, encrptedData.Length)

            length = encrptedData.Length
        End If

        ' Return the length that was written to the stream. 
        Return length

    End Function 'EncryptDataToStream


    Function DecryptDataFromStream(ByVal Entropy() As Byte, ByVal Scope As DataProtectionScope, ByVal S As Stream, ByVal Length As Integer) As Byte()
        If S Is Nothing Then
            Throw New ArgumentNullException("S")
        End If
        If Length <= 0 Then
            Throw New ArgumentException("Length")
        End If
        If Entropy Is Nothing Then
            Throw New ArgumentNullException("Entropy")
        End If
        If Entropy.Length <= 0 Then
            Throw New ArgumentException("Entropy")
        End If


        Dim inBuffer(Length) As Byte
        Dim outBuffer() As Byte

        ' Read the encrypted data from a stream.
        If S.CanRead Then
            S.Read(inBuffer, 0, Length)

            outBuffer = ProtectedData.Unprotect(inBuffer, Entropy, Scope)
        Else
            Throw New IOException("Could not read the stream.")
        End If

        ' Return the length that was written to the stream. 
        Return outBuffer

    End Function 'DecryptDataFromStream 
End Module 'MemoryProtectionSample
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

public class MemoryProtectionSample
{
    public static void Main()
    {
        Run();
    }

    public static void Run()
    {
        try
        {

            ///////////////////////////////
            //
            // Memory Encryption - ProtectedMemory
            //
            ///////////////////////////////

            // Create the original data to be encrypted (The data length should be a multiple of 16).
            byte[] toEncrypt = UnicodeEncoding.ASCII.GetBytes("ThisIsSomeData16");

            Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(toEncrypt));
            Console.WriteLine("Encrypting...");

            // Encrypt the data in memory.
            EncryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon);

            Console.WriteLine("Encrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt));
            Console.WriteLine("Decrypting...");

            // Decrypt the data in memory.
            DecryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon);

            Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt));


            ///////////////////////////////
            //
            // Data Encryption - ProtectedData
            //
            ///////////////////////////////

            // Create the original data to be encrypted
            toEncrypt = UnicodeEncoding.ASCII.GetBytes("This is some data of any length.");

            // Create a file.
            FileStream fStream = new FileStream("Data.dat", FileMode.OpenOrCreate);

            // Create some random entropy.
            byte[] entropy = CreateRandomEntropy();

            Console.WriteLine();
            Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(toEncrypt));
            Console.WriteLine("Encrypting and writing to disk...");

            // Encrypt a copy of the data to the stream.
            int bytesWritten = EncryptDataToStream(toEncrypt, entropy, DataProtectionScope.CurrentUser, fStream);

            fStream.Close();

            Console.WriteLine("Reading data from disk and decrypting...");

            // Open the file.
            fStream = new FileStream("Data.dat", FileMode.Open);

            // Read from the stream and decrypt the data.
            byte[] decryptData = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, bytesWritten);

            fStream.Close();

            Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(decryptData));


        }
        catch (Exception e)
        {
            Console.WriteLine("ERROR: " + e.Message);
        }

    }


    public static void EncryptInMemoryData(byte[] Buffer, MemoryProtectionScope Scope )
    {
        if (Buffer.Length <= 0)
            throw new ArgumentException("Buffer");
        if (Buffer == null)
            throw new ArgumentNullException("Buffer");


        // Encrypt the data in memory. The result is stored in the same same array as the original data.
        ProtectedMemory.Protect(Buffer, Scope);

    }

    public static void DecryptInMemoryData(byte[] Buffer, MemoryProtectionScope Scope)
    {
        if (Buffer.Length <= 0)
            throw new ArgumentException("Buffer");
        if (Buffer == null)
            throw new ArgumentNullException("Buffer");


        // Decrypt the data in memory. The result is stored in the same same array as the original data.
        ProtectedMemory.Unprotect(Buffer, Scope);

    }

    public static byte[] CreateRandomEntropy()
    {
        // Create a byte array to hold the random value.
        byte[] entropy = new byte[16];

        // Create a new instance of the RNGCryptoServiceProvider.
        // Fill the array with a random value.
        new RNGCryptoServiceProvider().GetBytes(entropy);

        // Return the array.
        return entropy;


    }

    public static int EncryptDataToStream(byte[] Buffer, byte[] Entropy, DataProtectionScope Scope, Stream S)
    {
        if (Buffer.Length <= 0)
            throw new ArgumentException("Buffer");
        if (Buffer == null)
            throw new ArgumentNullException("Buffer");
        if (Entropy.Length <= 0)
            throw new ArgumentException("Entropy");
        if (Entropy == null)
            throw new ArgumentNullException("Entropy");
        if (S == null)
            throw new ArgumentNullException("S");

        int length = 0;

        // Encrypt the data in memory. The result is stored in the same same array as the original data.
        byte[] encrptedData = ProtectedData.Protect(Buffer, Entropy, Scope);

        // Write the encrypted data to a stream.
        if (S.CanWrite && encrptedData != null)
        {
            S.Write(encrptedData, 0, encrptedData.Length);

            length = encrptedData.Length;
        }

        // Return the length that was written to the stream. 
        return length;

    }

    public static byte[] DecryptDataFromStream(byte[] Entropy, DataProtectionScope Scope, Stream S, int Length)
    {
        if (S == null)
            throw new ArgumentNullException("S");
        if (Length <= 0 )
            throw new ArgumentException("Length");
        if (Entropy == null)
            throw new ArgumentNullException("Entropy");
        if (Entropy.Length <= 0)
            throw new ArgumentException("Entropy");



        byte[] inBuffer = new byte[Length];
        byte[] outBuffer;

        // Read the encrypted data from a stream.
        if (S.CanRead)
        {
            S.Read(inBuffer, 0, Length);

            outBuffer = ProtectedData.Unprotect(inBuffer, Entropy, Scope);
        }
        else
        {
            throw new IOException("Could not read the stream.");
        }

        // Return the length that was written to the stream. 
        return outBuffer;

    }


}

Compilation du code

Voir aussi

Référence

ProtectedMemory

ProtectedData

Autres ressources

Tâches de chiffrement