Modèle de chiffrement .NET

.NET fournit des implémentations de nombreux algorithmes de chiffrement standard.

Héritage d’objets

Le système de chiffrement .NET implémente un modèle extensible d’héritage de classes dérivées. Cette hiérarchie se présente comme suit :

Ce modèle de classes dérivées vous permet d’ajouter un nouvel algorithme ou une nouvelle implémentation d’un algorithme existant. Par exemple, pour créer un algorithme de clé publique, vous devez hériter de la classe AsymmetricAlgorithm. Pour créer une nouvelle implémentation d'un algorithme spécifique, vous devez créer une classe non abstraite dérivée de cet algorithme.

Désormais, ce modèle d’héritage n’est pas utilisé pour les nouveaux types de primitives comme AesGcm ou Shake128. Ces algorithmes sont sealed. Si vous avez besoin d’un modèle d’extensibilité ou d’une abstraction sur ces types, l’implémentation de l’abstraction est la responsabilité du développeur.

API ponctuelles

À partir de .NET 5, des API plus simples ont été introduites pour le hachage et le HMAC. Bien qu’un peu moins flexibles, ces API ponctuelles :

  • sont plus faciles à utiliser (et moins sujettes à un mauvais usage) ;
  • limitent les allocations ou en sont exemptes ;
  • sont thread-safe ;
  • utilisent la meilleure implémentation disponible pour la plateforme.

Les primitives de hachage et HMAC exposent une API ponctuelle par le biais d’une méthode HashData statique sur le type, telle que SHA256.HashData. Les API statiques n’offrent aucun mécanisme d’extensibilité intégré. Si vous implémentez vos propres algorithmes, il est recommandé d’offrir également des API statiques similaires de l’algorithme.

La classe RandomNumberGenerator offre également des méthodes statiques pour créer ou remplir des mémoires tampons avec des données aléatoires de chiffrement. Ces méthodes utilisent toujours le générateur de nombres pseudo-aléatoires sécurisés par chiffrement (CSPRNG) du système.

Comment les algorithmes sont implémentés dans .NET

Prenez comme exemple d'implémentation les algorithmes symétriques. La base de tous les algorithmes symétriques est SymmetricAlgorithm, qui est hérité par Aes, TripleDES et d’autres qui ne sont plus recommandés.

Aes est héritée par AesCryptoServiceProvider, AesCng et AesManaged.

Dans .NET Framework sur Windows :

  • Les classes d’algorithme *CryptoServiceProvider telles que AesCryptoServiceProvider sont des wrappers autour de l’implémentation de l’API de chiffrement (CAPI, Cryptography API) Windows d’un algorithme.
  • Les classes d’algorithme *Cng telles que ECDiffieHellmanCng sont des wrappers autour de l’implémentation de CNG (Cryptography Next Generation) Windows.
  • Les classes *Managed telles que AesManaged sont écrites entièrement en code managé. Les implémentations *Managed ne sont pas certifiées par les normes FIPS (Federal Information Processing Standards) et peuvent être plus lentes que les classes wrapper *CryptoServiceProvider et *Cng.

Dans .NET Core et .NET 5 (et versions ultérieures), toutes les classes d’implémentation (*CryptoServiceProvider, *Managed et *Cng) sont des wrappers pour les algorithmes de système d’exploitation. Si les algorithmes de système d’exploitation sont certifiés FIPS, .NET utilise des algorithmes certifiés FIPS. Pour plus d’informations, consultez Chiffrement multiplateforme.

Dans la plupart des cas, vous n’avez pas besoin de référencer directement une classe d’implémentation d’algorithme telle que AesCryptoServiceProvider. Les méthodes et propriétés dont vous avez généralement besoin se trouvent dans la classe d’algorithme de base, par exemple Aes. Créez une instance d’une classe d’implémentation par défaut à l’aide d’une méthode de fabrique sur la classe d’algorithme de base, puis faites référence à la classe d’algorithme de base. Par exemple, consultez la ligne de code mise en évidence dans l’exemple suivant :

using System.Security.Cryptography;

try
{
    using (FileStream fileStream = new("TestData.txt", FileMode.OpenOrCreate))
    {
        using (Aes aes = Aes.Create())
        {
            byte[] key =
            {
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
            };
            aes.Key = key;

            byte[] iv = aes.IV;
            fileStream.Write(iv, 0, iv.Length);

            using (CryptoStream cryptoStream = new(
                fileStream,
                aes.CreateEncryptor(),
                CryptoStreamMode.Write))
            {
                // By default, the StreamWriter uses UTF-8 encoding.
                // To change the text encoding, pass the desired encoding as the second parameter.
                // For example, new StreamWriter(cryptoStream, Encoding.Unicode).
                using (StreamWriter encryptWriter = new(cryptoStream))
                {
                    encryptWriter.WriteLine("Hello World!");
                }
            }
        }
    }

    Console.WriteLine("The file was encrypted.");
}
catch (Exception ex)
{
    Console.WriteLine($"The encryption failed. {ex}");
}
Imports System
Imports System.IO
Imports System.Security.Cryptography

Module Module1
    Sub Main()
        Try
            ' Create a file stream
            Using fileStream As New FileStream("TestData.txt", FileMode.OpenOrCreate)

                ' Create a new instance of the default Aes implementation class  
                ' and configure encryption key.
                Using aes As Aes = Aes.Create()
                    'Encryption key used to encrypt the stream.
                    'The same value must be used to encrypt and decrypt the stream.
                    Dim key As Byte() = {
                        &H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8,
                        &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16
                    }

                    aes.Key = key

                    ' Stores IV at the beginning of the file.
                    ' This information will be used for decryption.
                    Dim iv As Byte() = aes.IV
                    fileStream.Write(iv, 0, iv.Length)

                    ' Create a CryptoStream, pass it the FileStream, and encrypt
                    ' it with the Aes class.
                    Using cryptoStream As New CryptoStream(fileStream, aes.CreateEncryptor(), CryptoStreamMode.Write)

                        ' By default, the StreamWriter uses UTF-8 encoding.
                        ' To change the text encoding, pass the desired encoding as the second parameter.
                        ' For example, New StreamWriter(cryptoStream, Encoding.Unicode).
                        Using sWriter As New StreamWriter(cryptoStream)

                            'Write to the stream.
                            sWriter.WriteLine("Hello World!")
                        End Using
                    End Using
                End Using
            End Using

            'Inform the user that the message was written  
            'to the stream.  
            Console.WriteLine("The text was encrypted.")
        Catch
            'Inform the user that an exception was raised.  
            Console.WriteLine("The encryption failed.")
            Throw
        End Try
    End Sub
End Module

Choisir un algorithme

Vous pouvez sélectionner un algorithme pour différentes raisons. Par exemple, pour l'intégrité ou la confidentialité des données, ou pour générer une clé. Les algorithmes symétriques et les algorithmes de hachage sont conçus pour protéger les données pour des raisons d'intégrité (empêcher leur modification) ou pour des raisons de confidentialité (empêcher leur affichage). Les algorithmes de hachage sont principalement utilisés pour l'intégrité des données.

Voici une liste des algorithmes recommandés pour chaque application :

Voir aussi