Compartilhar via


Modelo de criptografia .NET

O .NET fornece implementações de muitos algoritmos criptográficos padrão.

Herança de objetos

O sistema de criptografia .NET implementa um padrão extensível de herança de classe derivada. A hierarquia é a seguinte:

Esse padrão de classes derivadas permite adicionar um novo algoritmo ou uma nova implementação de um algoritmo existente. Por exemplo, para criar um novo algoritmo de chave pública, você herdaria da AsymmetricAlgorithm classe. Para criar uma nova implementação de um algoritmo específico, você criaria uma classe derivada não abstrata desse algoritmo.

Daqui para frente, esse modelo de herança não é usado para novos tipos de primitivos como AesGcm ou Shake128. Esses algoritmos são sealed. Se você precisar de um padrão de extensibilidade ou abstração sobre esses tipos, a implementação da abstração será de responsabilidade do desenvolvedor.

APIs de uso único

A partir do .NET 5, APIs mais simples foram introduzidas para hash e HMAC. Embora um pouco menos flexíveis, estas APIs de um disparo:

  • São mais fáceis de usar (e menos propensos a uso indevido)
  • Reduzir alocações ou estar livre de alocações
  • São seguras para thread
  • Usar a melhor implementação disponível para a plataforma

Os primitivos de hash e HMAC expõem uma API de um disparo por meio de um método HashData estático no tipo, como SHA256.HashData. As APIs estáticas não oferecem nenhum mecanismo de extensibilidade interno. Se você estiver implementando seus próprios algoritmos, é recomendável também oferecer APIs estáticas semelhantes do algoritmo.

A RandomNumberGenerator classe também oferece métodos estáticos para criar ou preencher buffers com dados aleatórios criptográficos. Esses métodos sempre usam o gerador de números pseudoaleatórios criptograficamente seguro do sistema (CSPRNG).

Como os algoritmos são implementados no .NET

Como exemplo das diferentes implementações disponíveis para um algoritmo, considere algoritmos simétricos. A base para todos os algoritmos simétricos é SymmetricAlgorithm, que é herdada por Aes, TripleDES e outras, que não são mais recomendadas.

Aes é herdado por AesCryptoServiceProvider, AesCnge AesManaged.

No .NET Framework no Windows:

  • As classes de algoritmo *CryptoServiceProvider, como AesCryptoServiceProvider, são wrappers em torno da implementação da CAPI (API de Criptografia do Windows) de um algoritmo.
  • As classes de algoritmo *Cng, como ECDiffieHellmanCng, são wrappers em torno da implementação CNG (Cryptography Next Generation) do Windows.
  • *Managed classes, como AesManaged, são escritas inteiramente em código gerenciado. *Managed as implementações não são certificadas pelos Padrões Federais de Processamento de Informações (FIPS) e podem ser mais lentas do que as classes wrapper *CryptoServiceProvider e *Cng.

No .NET Core e no .NET 5 e versões posteriores, todas as classes de implementação (*CryptoServiceProvidere *Managed*Cng) são wrappers para os algoritmos do sistema operacional (SO). Se os algoritmos do sistema operacional forem certificados por FIPS, o .NET usará algoritmos certificados por FIPS. Para obter mais informações, consulte Criptografia Multiplataforma.

Na maioria dos casos, você não precisa referenciar diretamente uma classe de implementação de algoritmo, como AesCryptoServiceProvider. Os métodos e as propriedades que você normalmente precisa estão na classe de algoritmo base, como Aes. Crie uma instância de uma classe de implementação padrão usando um método de fábrica na classe de algoritmo base e consulte a classe de algoritmo base. Por exemplo, consulte a linha de código realçada no exemplo a seguir:

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

Selecionar um algoritmo

Você pode selecionar um algoritmo por diferentes motivos: por exemplo, para integridade de dados, para privacidade de dados ou para gerar uma chave. Algoritmos simétricos e de hash são destinados à proteção de dados por motivos de integridade (proteção contra alteração) ou motivos de privacidade (proteção contra exibição). Algoritmos de hash são usados principalmente para integridade de dados.

Aqui está uma lista de algoritmos recomendados por aplicativo:

Consulte também