Encrypting data (Cifrado de datos)
El cifrado simétrico y el cifrado asimétrico se efectúan mediante procesos distintos. El cifrado simétrico se realiza en secuencias y, por tanto, resulta útil para cifrar grandes cantidades de datos. El cifrado asimétrico se realiza en un pequeño número de bytes y, por tanto, solo resulta útil para pequeñas cantidades de datos.
Cifrado simétrico
Las clases de criptografía simétrica administrada se usan con una clase de secuencia especial llamada CryptoStream que cifra los datos leídos en la secuencia. La clase CryptoStream se inicializa con una clase de secuencia administrada, una clase que implementa la interfaz ICryptoTransform (creada a partir de una clase que implementa un algoritmo criptográfico) y una enumeración CryptoStreamMode que describe el tipo de acceso permitido a CryptoStream. La clase CryptoStream puede inicializarse usando cualquier clase que derive de la clase Stream , incluidas FileStream, MemoryStreamy NetworkStream. Mediante estas clases, puede realizar el cifrado simétrico en diversos objetos de secuencia.
En el ejemplo siguiente se muestra cómo crear una nueva instancia de la clase de implementación predeterminada del algoritmo Aes. La instancia se usa para realizar el cifrado en una clase CryptoStream. En este ejemplo, CryptoStream se inicializa con un objeto de secuencia llamado fileStream
que puede ser cualquier tipo de secuencia administrada. La clave y el IV que se usan para el cifrado pasan el método CreateEncryptor de la clase Aes. En este caso, se usan la clave predeterminada y el IV generados desde 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);
Después de que se ejecute este código, los datos escritos en el objeto CryptoStream se cifran mediante el algoritmo AES.
En el ejemplo siguiente se muestra todo el proceso de crear una secuencia, cifrarla, escribir en ella y cerrarla. En este ejemplo se crea una secuencia de archivos que se cifra mediante las clases CryptoStream y Aes. El IV generado se escribe al principio de FileStream, por lo que se puede leer y usar para el descifrado. A continuación, se escribe un mensaje en la secuencia cifrada con la clase StreamWriter. Aunque la misma clave se puede usar varias veces para cifrar y descifrar datos, se recomienda generar un nuevo IV aleatorio cada vez. De este modo, los datos cifrados siempre son diferentes, incluso cuando el texto sin formato es el mismo.
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
El código cifra la secuencia mediante el algoritmo simétrico AES y escribe IV y, a continuación, cifra "Hola mundo" en la secuencia. Si el código se ejecuta correctamente, crea un archivo cifrado denominado TestData.txt y muestra el texto siguiente en la consola:
The file was encrypted.
Puede descifrar el archivo mediante el ejemplo de descifrado simétrico de Descifrar datos. Ese ejemplo y este ejemplo especifican la misma clave.
Sin embargo, si se produce una excepción, el código muestra el texto siguiente en la consola:
The encryption failed.
Cifrado asimétrico
Los algoritmos asimétricos suelen usarse para cifrar pequeñas cantidades de datos, como el cifrado de una clave simétrica y un IV. Normalmente, cuando se realiza un cifrado asimétrico, se usa la clave pública generada por terceros. .NET proporciona la clase RSA necesaria para este propósito.
En el ejemplo siguiente se usa la información de clave pública para cifrar una clave simétrica y un IV. Se inicializan dos matrices de bytes que representan la clave pública de un tercero. Se inicializa un objeto RSAParameters en estos valores. A continuación, el objeto RSAParameters (junto con la clave pública que representa) se importa en una instancia de RSA mediante el método RSA.ImportParameters. Por último, se cifran la clave privada y el IV creados por una clase Aes. Este ejemplo requiere sistemas que tengan instalado el cifrado de 128 bits.
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);
}
}