Modelo de criptografia .NET
O .NET fornece implementações de muitos algoritmos criptográficos padrão.
Herança de objeto
O sistema de criptografia .NET implementa um padrão extensível de herança de classe derivada. A hierarquia é a seguinte:
Classe de tipo de algoritmo, como SymmetricAlgorithm, AsymmetricAlgorithmou HashAlgorithm. Este nível é abstrato.
Classe de algoritmo que herda de uma classe de tipo de algoritmo, por exemplo, Aes, RSA, ou ECDiffieHellman. Este nível é abstrato.
Implementação de uma classe de algoritmo que herda de uma classe de algoritmo, por exemplo, AesManaged, RC2CryptoServiceProvider, ou ECDiffieHellmanCng. Este nível é plenamente implementado.
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.
No futuro, este modelo de herança não é usado para novos tipos de primitivos como AesGcm ou Shake128. Estes 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 é de responsabilidade do desenvolvedor.
One-shot APIs
A partir do .NET 5, APIs mais simples foram introduzidas para hashing e HMAC. Embora um pouco menos flexíveis, estas APIs one-shot :
- São mais fáceis de usar (e menos propensos a uso indevido)
- Reduzir alocações ou são livres de alocação
- São thread safe
- Use a melhor implementação disponível para a plataforma
As primitivas hashing e HMAC expõem uma API one-shot por meio de um método estático HashData
no tipo, como SHA256.HashData. As APIs estáticas não oferecem nenhum mecanismo de extensibilidade integrado. 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 (CSPRNG) do sistema.
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 é herdado por Aes, TripleDESe outros que não são mais recomendados.
Aes é herdada por AesCryptoServiceProvider, AesCnge AesManaged.
No .NET Framework no Windows:
*CryptoServiceProvider
classes de algoritmo, como AesCryptoServiceProvider, são wrappers em torno da implementação da API de Criptografia do Windows (CAPI) de um algoritmo.*Cng
classes de algoritmo, como ECDiffieHellmanCng, são wrappers em torno da implementação do Windows Cryptography Next Generation (CNG).*Managed
classes, como AesManaged, são escritas inteiramente em código gerenciado.*Managed
as implementações não são certificadas pelo Federal Information Processing Standards (FIPS) e podem ser mais lentas do que as*CryptoServiceProvider
classes e*Cng
wrapper.
No .NET Core e no .NET 5 e versões posteriores, todas as classes de implementação (*CryptoServiceProvider
, *Managed
e *Cng
) são wrappers para os algoritmos do sistema operacional (SO). Se os algoritmos do sistema operacional tiverem certificação FIPS, o .NET usará algoritmos certificados por FIPS. Para obter mais informações, consulte Criptografia entre plataformas.
Na maioria dos casos, você não precisa fazer referência direta a uma classe de implementação de algoritmo, como AesCryptoServiceProvider
. Os métodos e propriedades de 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
Escolha 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. Os algoritmos simétricos e de hash destinam-se a proteger os dados por razões de integridade (proteger contra alterações) ou de privacidade (proteger contra visualização). Os algoritmos de hash são usados principalmente para integridade de dados.
Aqui está uma lista de algoritmos recomendados por aplicação:
- Privacidade de dados:
- Integridade dos dados:
- Assinatura digital:
- Troca de chaves:
- Geração de números aleatórios:
- Gerando uma chave a partir de uma senha: