Прочитать на английском

Поделиться через


Шифрование данных

Симметричное и асимметричное шифрования выполняются с использованием различных процессов. Симметричное шифрование выполняется в рамках потоков, поэтому его удобно применять для шифрования больших объемов данных. Асимметричное шифрование выполняется в рамках небольшого числа байтов, поэтому его удобно применять для шифрования только небольших объемов данных.

Симметричное шифрование

Управляемые классы симметричного шифрования используются со специальным классом потока CryptoStream , который шифрует данные, считанные в поток. Класс CryptoStream инициализирован с помощью управляемого класса потока, класса, реализующего ICryptoTransform интерфейс (созданный из класса, реализующего криптографический алгоритм), и CryptoStreamMode перечисление, описывающее тип доступа, разрешенный к CryptoStream. Класс CryptoStream может быть инициализирован при помощи любого класса, производного от класса Stream , включая FileStream, MemoryStreamи NetworkStream. При помощи этих классов можно осуществлять симметричное шифрование для различных объектов потока.

В следующем примере показано, как создать новый экземпляр класса реализации по умолчанию для алгоритма Aes . Экземпляр используется для шифрования класса CryptoStream . В этом примере CryptoStream инициализируется при помощи объекта потока fileStream , который может быть любым типом управляемого потока. Метод CreateEncryptor из класса Aes передает ключ и IV, используемые для шифрования. В этом случае используется ключ и вектор инициализации по умолчанию, созданные из aes .

C#
Aes aes = Aes.Create();
CryptoStream cryptStream = new CryptoStream(
    fileStream, aes.CreateEncryptor(key, iv), CryptoStreamMode.Write);

После выполнения этого кода все данные, записанные в объект CryptoStream , шифруются с помощью алгоритма AES.

В следующем примере показан весь процесс создания потока, шифрования потока, чтения из потока и закрытия потока. В этом примере создается файловый поток, зашифрованный с помощью класса CryptoStream и класса Aes . Созданный IV записывается в начало FileStream, поэтому его можно считывать и использовать для расшифровки. Затем сообщение записывается в зашифрованный поток с StreamWriter помощью класса. Хотя один и тот же ключ можно использовать несколько раз для шифрования и расшифровки данных, рекомендуется создавать новый случайный IV каждый раз. Таким образом зашифрованные данные всегда отличаются, даже если обычный текст совпадает.

C#
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}");
}

Код шифрует поток с помощью симметричного алгоритма AES и записывает IV, а затем шифрует "Hello World!" в поток. Если код выполнен успешно, он создает зашифрованный файл с именем TestData.txt и отображает следующий текст в консоли:

Консоль
The file was encrypted.

Файл можно расшифровать с помощью примера симметричного расшифровки в расшифровке данных. Этот пример и этот пример указывают один и тот же ключ.

Однако если возникает исключение, код отображает следующий текст в консоли:

Консоль
The encryption failed.

Асимметричное шифрование

Асимметричные алгоритмы обычно используются для шифрования малых объемов данных, например для шифрования симметричного ключа и вектора инициализации. Как правило, сторона, осуществляющая асимметричное шифрование, использует открытый ключ, созданный другой стороной. Класс RSA предоставляется .NET для этой цели.

В следующем примере сведения об открытом ключе используются для шифрования симметричного ключа и вектора инициализации. Два массива байтов инициализированы, представляющие открытый ключ стороннего производителя. Объект RSAParameters инициализируется с этими значениями. Затем объект RSAParameters (вместе с открытым ключом, который он представляет) импортируется в экземпляр RSA с помощью RSA.ImportParameters метода. Наконец, закрытый ключ и IV, созданные классом Aes , шифруются. В этом примере требуется, чтобы в системе было установлено 128-битное шифрование.

C#
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);
    }
}

См. также