Criptografando dados
A criptografia simétrica e a criptografia assimétrica são executadas usando processos diferentes. A criptografia simétrica é executada em fluxos, portanto, é útil para criptografar grandes quantidades de dados. A criptografia assimétrica é executada em um pequeno número de bytes, portanto, é útil apenas para pequenas quantidades de dados.
Criptografia simétrica
As classes de criptografia simétrica gerenciada são usadas com uma classe de fluxo especial chamada CryptoStream, que criptografa os dados lidos no fluxo. A classe CryptoStream é inicializada com uma classe de fluxo gerenciada, uma classe que implementa a interface ICryptoTransform (criada com base em uma classe que implementa um algoritmo de criptografia) e uma enumeração CryptoStreamMode que descreve o tipo de acesso permitido ao CryptoStream. A classe CryptoStream pode ser inicializada usando qualquer classe derivada da classe Stream, incluindo FileStream, MemoryStream e NetworkStream. Usando essas classes, você pode executar criptografia simétrica em uma variedade de objetos de fluxo.
O exemplo a seguir ilustra como criar uma instância da classe de implementação padrão para o algoritmo Aes. A instância é usada para executar criptografia em uma classe CryptoStream. Neste exemplo, o CryptoStream é inicializado com um objeto de fluxo chamado fileStream
que pode ser qualquer tipo de fluxo gerenciado. O método CreateEncryptor da classe Aes é passado para a chave e o IV que são usados para criptografia. Nesse caso, a chave padrão e o IV gerados de aes
são usados.
Dim aes As Aes = Aes.Create()
Dim cryptStream As New CryptoStream(
fileStream, aes.CreateEncryptor(key, iv), CryptoStreamMode.Write)
Aes aes = Aes.Create();
CryptoStream cryptStream = new CryptoStream(
fileStream, aes.CreateEncryptor(key, iv), CryptoStreamMode.Write);
Depois que esse código é executado, todos os dados gravados no objeto CryptoStream são criptografados usando o algoritmo AES.
O exemplo a seguir mostra todo o processo de criação de um fluxo, criptografia do fluxo, gravação no fluxo e fechamento do fluxo. Este exemplo cria um fluxo de arquivos criptografado usando a classe CryptoStream e a classe Aes. O Generated IV é gravado no início de FileStream, portanto, ele pode ser lido e usado para descriptografia. Em seguida, uma mensagem é gravada no fluxo criptografado com a classe StreamWriter. Embora a mesma chave possa ser usada várias vezes para criptografar e descriptografar dados, é recomendável gerar um IV aleatório novo a cada vez. Dessa forma, os dados criptografados são sempre diferentes, mesmo quando o texto sem formatação é o mesmo.
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
O código criptografa o fluxo usando o algoritmo simétrico do AES e grava IV e criptografado "Olá, Mundo!" no fluxo. Se o código for bem-sucedido, ele criará um arquivo criptografado chamado TestData.txt e exibirá o seguinte texto para o console:
The file was encrypted.
Você pode descriptografar o arquivo usando o exemplo de descriptografia simétrica em Como descriptografar dados. Aquele exemplo e este exemplo especificam a mesma chave.
No entanto, se uma exceção for gerada, o código exibirá o seguinte texto para o console:
The encryption failed.
Criptografia assimétrica
Algoritmos assimétricos geralmente são usados para criptografar pequenas quantidades de dados, como a criptografia de uma chave simétrica e IV. Normalmente, um indivíduo que executa criptografia assimétrica usa a chave pública gerada por outra parte. A classe RSA é fornecida pelo .NET para essa finalidade.
O exemplo a seguir usa informações de chave pública para criptografar uma chave simétrica e IV. Duas matrizes de bytes são inicializadas que representam a chave pública de terceiros. Um objeto RSAParameters é inicializado para esses valores. Em seguida, o objeto RSAParameters (juntamente com a chave pública que ele representa) é importado para uma instância RSA usando o método RSA.ImportParameters. Por fim, a chave privada e o IV criados por uma classe Aes são criptografados. Este exemplo exige que os sistemas tenham a criptografia de 128 bits instalada.
Imports System
Imports System.Security.Cryptography
Module Module1
Sub Main()
'Initialize the byte arrays to the public key information.
Dim modulus As Byte() = {214, 46, 220, 83, 160, 73, 40, 39, 201, 155, 19, 202, 3, 11, 191, 178, 56, 74, 90, 36, 248, 103, 18, 144, 170, 163, 145, 87, 54, 61, 34, 220, 222, 207, 137, 149, 173, 14, 92, 120, 206, 222, 158, 28, 40, 24, 30, 16, 175, 108, 128, 35, 230, 118, 40, 121, 113, 125, 216, 130, 11, 24, 90, 48, 194, 240, 105, 44, 76, 34, 57, 249, 228, 125, 80, 38, 9, 136, 29, 117, 207, 139, 168, 181, 85, 137, 126, 10, 126, 242, 120, 247, 121, 8, 100, 12, 201, 171, 38, 226, 193, 180, 190, 117, 177, 87, 143, 242, 213, 11, 44, 180, 113, 93, 106, 99, 179, 68, 175, 211, 164, 116, 64, 148, 226, 254, 172, 147}
Dim exponent As Byte() = {1, 0, 1}
'Create values to store encrypted symmetric keys.
Dim encryptedSymmetricKey() As Byte
Dim encryptedSymmetricIV() As Byte
'Create a new instance of the default RSA implementation class.
Dim rsa As RSA = RSA.Create()
'Create a new instance of the RSAParameters structure.
Dim rsaKeyInfo As New RSAParameters()
'Set rsaKeyInfo to the public key values.
rsaKeyInfo.Modulus = modulus
rsaKeyInfo.Exponent = exponent
'Import key parameters into rsa
rsa.ImportParameters(rsaKeyInfo)
'Create a new instance of the default Aes implementation class.
Dim aes As Aes = Aes.Create()
'Encrypt the symmetric key and IV.
encryptedSymmetricKey = rsa.Encrypt(aes.Key, RSAEncryptionPadding.Pkcs1)
encryptedSymmetricIV = rsa.Encrypt(aes.IV, RSAEncryptionPadding.Pkcs1)
End Sub
End Module
using System;
using System.Security.Cryptography;
class Class1
{
static void Main()
{
//Initialize the byte arrays to the public key information.
byte[] modulus =
{
214,46,220,83,160,73,40,39,201,155,19,202,3,11,191,178,56,
74,90,36,248,103,18,144,170,163,145,87,54,61,34,220,222,
207,137,149,173,14,92,120,206,222,158,28,40,24,30,16,175,
108,128,35,230,118,40,121,113,125,216,130,11,24,90,48,194,
240,105,44,76,34,57,249,228,125,80,38,9,136,29,117,207,139,
168,181,85,137,126,10,126,242,120,247,121,8,100,12,201,171,
38,226,193,180,190,117,177,87,143,242,213,11,44,180,113,93,
106,99,179,68,175,211,164,116,64,148,226,254,172,147
};
byte[] exponent = { 1, 0, 1 };
//Create values to store encrypted symmetric keys.
byte[] encryptedSymmetricKey;
byte[] encryptedSymmetricIV;
//Create a new instance of the RSA class.
RSA rsa = RSA.Create();
//Create a new instance of the RSAParameters structure.
RSAParameters rsaKeyInfo = new RSAParameters();
//Set rsaKeyInfo to the public key values.
rsaKeyInfo.Modulus = modulus;
rsaKeyInfo.Exponent = exponent;
//Import key parameters into rsa.
rsa.ImportParameters(rsaKeyInfo);
//Create a new instance of the default Aes implementation class.
Aes aes = Aes.Create();
//Encrypt the symmetric key and IV.
encryptedSymmetricKey = rsa.Encrypt(aes.Key, RSAEncryptionPadding.Pkcs1);
encryptedSymmetricIV = rsa.Encrypt(aes.IV, RSAEncryptionPadding.Pkcs1);
}
}