Crittografia dei dati
La crittografia simmetrica e quella asimmetrica vengono eseguite usando processi diversi. La crittografia simmetrica viene eseguita sui flussi e di conseguenza è utile per crittografare grandi quantità di dati. La crittografia asimmetrica viene eseguita su un numero ridotto di byte e di conseguenza è utile solo per piccole quantità di dati.
Crittografia simmetrica
Le classi di crittografia simmetrica gestite vengono usate con una classe di flusso speciale chiamata CryptoStream , che crittografa i dati letti nel flusso. La classe CryptoStream viene inizializzata con una classe di flusso gestita, una classe che implementa l'interfaccia ICryptoTransform (creata da una classe che implementa un algoritmo di crittografia) e un'enumerazione CryptoStreamMode che descrive il tipo di accesso consentito alla classe CryptoStream. La classe CryptoStream può essere inizializzata usando qualsiasi classe derivata dalla classe Stream , tra cui FileStream, MemoryStreame NetworkStream. Usando queste classi, è possibile eseguire crittografia simmetrica su svariati oggetti flusso.
Nell'esempio seguente viene illustrato come creare una nuova istanza della classe di implementazione predefinita per l'algoritmo Aes. L'istanza viene usata per eseguire la crittografia in una classe CryptoStream. In questo esempio la classe CryptoStream viene inizializzata con un oggetto flusso chiamato fileStream
, che può essere qualsiasi tipo di flusso gestito. Al metodo CreateEncryptor della classe Aes vengono passati la chiave e il vettore di inizializzazione usati per la crittografia. In questo caso, vengono usati la chiave e il vettore di inizializzazione predefiniti generati da aes
.
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);
Una volta eseguito questo codice, tutti i dati scritti nell'oggetto CryptoStream vengono crittografati usando l'algoritmo AES.
L'esempio seguente illustra l'intero processo di creazione di un flusso, decrittografia del flusso, scrittura nel flusso e chiusura del flusso. In questo esempio viene creato un flusso di file crittografato usando la classe CryptoStream e la classe Aes. L'IV generato viene scritto all'inizio di FileStream, quindi può essere letto e usato per la decrittografia. Viene quindi scritto un messaggio al flusso crittografato con la classe StreamWriter. Anche se la stessa chiave può essere usata più volte per crittografare e decrittografare i dati, è consigliabile generare un nuovo IV casuale ogni volta. In questo modo i dati crittografati sono sempre diversi, anche quando il testo normale è lo stesso.
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
Il codice crittografa il flusso usando l'algoritmo simmetrico AES e scrive l’IV e quindi crittografa "Hello World!" nel flusso. Se il codice ha esito positivo, crea un file crittografato denominato TestData.txt e visualizza il testo seguente nella console:
The file was encrypted.
È possibile decrittografare il file usando l'esempio di decrittografia simmetrica in Decrittografia dei dati. Quell’esempio e questo esempio specificano la stessa chiave.
Tuttavia, se viene generata un'eccezione, il codice visualizza il testo seguente nella console:
The encryption failed.
Crittografia asimmetrica
Gli algoritmi asimmetrici vengono in genere usati per crittografare piccole quantità di dati, ad esempio per la crittografia di una chiave simmetrica e un vettore di inizializzazione. In genere, un utente che esegue la crittografia asimmetrica usa la chiave pubblica generata da un'altra parte. La classe RSA viene fornita da .NET a questo scopo.
L'esempio seguente usa le informazioni della chiave pubblica per crittografare una chiave simmetrica e un vettore di inizializzazione. Vengono inizializzate due matrici di byte che rappresentano la chiave pubblica di una terza parte. Viene inizializzato un oggetto RSAParameters su questi valori. Quindi, l'oggetto RSAParameters (insieme alla chiave pubblica che rappresenta) viene importato in un’istanza RSA usando il metodo RSA.ImportParameters. Vengono infine crittografati la chiave privata e il vettore di inizializzazione creati da una classe Aes. Per questo esempio, è necessario che nei sistemi siano installati strumenti di crittografia a 128 bit.
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);
}
}