Полное руководство по использованию ГОСТ-криптографии в .NET

  • Михаил
  • 8 мин. на прочтение
  • 37
  • 14 Jun 2025
  • 14 Jun 2025

В этом подробном руководстве я покажу использование всех основных криптографических алгоритмов ГОСТ 2012 года, включая хеширование, симметричное и асимметричное шифрование, электронную подпись.

using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using GostCryptography.Base;
using GostCryptography.Gost_R3410;
using GostCryptography.Gost_R3411;
using GostCryptography.Gost_28147_89;
public class Program
{
   public static void Main()
   {
       try
       {
           Console.WriteLine("=== ПОЛНОЕ РУКОВОДСТВО ПО ГОСТ-КРИПТОГРАФИИ (2012) ===");
           Console.WriteLine("Демонстрация алгоритмов ГОСТ 2012 года:\n" +
                             "1. Хеширование по ГОСТ Р 34.11-2012\n" +
                             "2. Симметричное шифрование по ГОСТ 28147-89\n" +
                             "3. Асимметричное шифрование по ГОСТ Р 34.10-2012\n" +
                             "4. Электронная подпись по ГОСТ Р 34.10-2012\n");
           
           // 1. Проверка окружения
           CheckEnvironment();
           
           // 2. Демонстрация хеширования
           DemonstrateHashing();
           
           // 3. Демонстрация симметричного шифрования
           DemonstrateSymmetricEncryption();
           
           // 4. Демонстрация асимметричных операций
           DemonstrateAsymmetricOperations();
       }
       catch (Exception ex)
       {
           Console.WriteLine($"\n❌ Критическая ошибка: {ex.Message}");
           Console.WriteLine(ex.StackTrace);
       }
       finally
       {
           Console.WriteLine("\nНажмите любую клавишу для выхода...");
           Console.ReadKey();
       }
   }
   /// <summary>
   /// Проверка окружения: установлен ли КриптоПро и есть ли сертификаты
   /// </summary>
   private static void CheckEnvironment()
   {
       Console.WriteLine("\n=== 1. ПРОВЕРКА ОКРУЖЕНИЯ ===");
       // 1.1. Проверка наличия КриптоПро CSP
       Console.WriteLine("\n[1.1] Проверка установки КриптоПро CSP...");
       try
       {
           using (var hash = new Gost_R3411_2012_512_HashAlgorithm())
           {
               Console.WriteLine("✅ КриптоПро CSP доступен");
           }
       }
       catch (Exception ex)
       {
           throw new Exception("КриптоПро CSP не установлен или не доступен. Ошибка: " + ex.Message);
       }
       // 1.2. Проверка наличия сертификатов
       Console.WriteLine("\n[1.2] Поиск сертификатов ГОСТ Р 34.10-2012...");
       var certificates = FindGostCertificates();
       
       if (certificates.Count == 0)
       {
           Console.WriteLine("⚠ Предупреждение: Не найдено сертификатов ГОСТ Р 34.10-2012");
       }
       else
       {
           Console.WriteLine($"Найдено сертификатов: {certificates.Count}");
           foreach (var cert in certificates)
           {
               Console.WriteLine($"- {cert.SubjectName.Name} (SN: {cert.SerialNumber}, " +
                                 $"Alg: {cert.PublicKey.Oid.FriendlyName}, " +
                                 $"HasPrivateKey: {cert.HasPrivateKey})");
           }
       }
   }
   /// <summary>
   /// Поиск сертификатов ГОСТ Р 34.10-2012 в хранилищах
   /// </summary>
   private static X509Certificate2Collection FindGostCertificates()
   {
       var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
       store.Open(OpenFlags.ReadOnly);
       
       var certificates = new X509Certificate2Collection();
       
       // OID для ГОСТ Р 34.10-2012 (256 бит)
       const string GOST_3410_2012_256_OID = "1.2.643.7.1.1.1.1";
       // OID для ГОСТ Р 34.10-2012 (512 бит)
       const string GOST_3410_2012_512_OID = "1.2.643.7.1.1.1.2";
       
       foreach (var cert in store.Certificates)
       {
           if (cert.PublicKey.Oid.Value == GOST_3410_2012_256_OID || 
               cert.PublicKey.Oid.Value == GOST_3410_2012_512_OID)
           {
               certificates.Add(cert);
           }
       }
       
       store.Close();
       return certificates;
   }
   /// <summary>
   /// Демонстрация хеширования по ГОСТ Р 34.11-2012
   /// </summary>
   private static void DemonstrateHashing()
   {
       Console.WriteLine("\n=== 2. ХЕШИРОВАНИЕ (ГОСТ Р 34.11-2012) ===");
       
       // Тестовые данные
       byte[] data = System.Text.Encoding.UTF8.GetBytes("Российская Федерация - государство в Восточной Европе и Северной Азии.");
       Console.WriteLine($"\n[2.1] Исходные данные ({data.Length} байт):");
       Console.WriteLine(BitConverter.ToString(data).Replace("-", ""));
       // 2.1. ГОСТ Р 34.11-2012 (256 бит)
       Console.WriteLine("\n[2.2] Хеширование ГОСТ Р 34.11-2012 (256 бит):");
       using (var hashAlg = new Gost_R3411_2012_256_HashAlgorithm())
       {
           byte[] hash = hashAlg.ComputeHash(data);
           Console.WriteLine($"Размер хеша: {hash.Length} байт ({hash.Length*8} бит)");
           Console.WriteLine($"Хеш: {BitConverter.ToString(hash).Replace("-", "")}");
           
           // Проверка на идентичных данных
           byte[] hash2 = hashAlg.ComputeHash(data);
           Console.WriteLine($"Хеши идентичных данных совпадают: {hash.SequenceEqual(hash2)}");
           
           // Проверка на разных данных
           byte[] modifiedData = (byte[])data.Clone();
           modifiedData[0] ^= 0xFF; // Изменяем первый байт
           byte[] modifiedHash = hashAlg.ComputeHash(modifiedData);
           Console.WriteLine($"Хеши разных данных отличаются: {!hash.SequenceEqual(modifiedHash)}");
       }
       // 2.2. ГОСТ Р 34.11-2012 (512 бит)
       Console.WriteLine("\n[2.3] Хеширование ГОСТ Р 34.11-2012 (512 бит):");
       using (var hashAlg = new Gost_R3411_2012_512_HashAlgorithm())
       {
           byte[] hash = hashAlg.ComputeHash(data);
           Console.WriteLine($"Размер хеша: {hash.Length} байт ({hash.Length*8} бит)");
           Console.WriteLine($"Хеш: {BitConverter.ToString(hash).Replace("-", "")}");
           
           // Проверка устойчивости к коллизиям
           Console.WriteLine("\n[2.4] Проверка устойчивости к коллизиям:");
           TestHashCollisionResistance(hashAlg);
       }
   }
   /// <summary>
   /// Тестирование устойчивости хеш-функции к коллизиям
   /// </summary>
   private static void TestHashCollisionResistance(HashAlgorithm hashAlg)
   {
       int attempts = 1000;
       int collisionLength = 4; // Проверяем коллизии первых 4 байт
       var hashes = new System.Collections.Generic.HashSet<string>();
       int collisions = 0;
       
       byte[] testData = new byte[32];
       new Random().NextBytes(testData);
       for (int i = 0; i < attempts; i++)
       {
           // Немного изменяем данные
           testData[0] = (byte)i;
           testData[1] = (byte)(i >> 8);
           
           byte[] hash = hashAlg.ComputeHash(testData);
           string hashPrefix = BitConverter.ToString(hash, 0, collisionLength);
           
           if (!hashes.Add(hashPrefix))
           {
               collisions++;
           }
       }
       
       Console.WriteLine($"Попыток: {attempts}, коллизий (первые {collisionLength} байт): {collisions}");
       Console.WriteLine($"Процент коллизий: {collisions * 100.0 / attempts:F2}%");
   }
   /// <summary>
   /// Демонстрация симметричного шифрования (ГОСТ 28147-89)
   /// </summary>
   private static void DemonstrateSymmetricEncryption()
   {
       Console.WriteLine("\n=== 3. СИММЕТРИЧНОЕ ШИФРОВАНИЕ (ГОСТ 28147-89) ===");
       
       // 3.1. Подготовка данных
       string originalText = "Конфиденциальная информация, требующая защиты.";
       byte[] data = System.Text.Encoding.UTF8.GetBytes(originalText);
       
       Console.WriteLine($"\n[3.1] Исходные данные ({data.Length} байт):");
       Console.WriteLine($"Текст: {originalText}");
       Console.WriteLine($"Байты: {BitConverter.ToString(data).Replace("-", "")}");
       // 3.2. Создание алгоритма шифрования
       Console.WriteLine("\n[3.2] Инициализация алгоритма ГОСТ 28147-89...");
       using (var cipher = new Gost_28147_89_SymmetricAlgorithm())
       {
           // Важно! Для реальных проектов используйте безопасную генерацию ключей
           cipher.GenerateKey(); // 256-битный ключ
           cipher.GenerateIV();  // 64-битный вектор инициализации
           
           Console.WriteLine($"Ключ: {BitConverter.ToString(cipher.Key).Replace("-", "")}");
           Console.WriteLine($"IV: {BitConverter.ToString(cipher.IV).Replace("-", "")}");
           // 3.3. Шифрование в режиме CBC (Cipher Block Chaining)
           Console.WriteLine("\n[3.3] Шифрование данных (режим CBC)...");
           cipher.Mode = CipherMode.CBC;
           cipher.Padding = PaddingMode.PKCS7;
           
           byte[] encrypted;
           using (var encryptor = cipher.CreateEncryptor())
           using (var ms = new MemoryStream())
           using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
           {
               cs.Write(data, 0, data.Length);
               cs.FlushFinalBlock();
               encrypted = ms.ToArray();
           }
           
           Console.WriteLine($"Зашифрованные данные ({encrypted.Length} байт):");
           Console.WriteLine(BitConverter.ToString(encrypted).Replace("-", ""));
           // 3.4. Дешифрование
           Console.WriteLine("\n[3.4] Дешифрование данных...");
           byte[] decrypted;
           using (var decryptor = cipher.CreateDecryptor())
           using (var ms = new MemoryStream(encrypted))
           using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
           using (var output = new MemoryStream())
           {
               cs.CopyTo(output);
               decrypted = output.ToArray();
           }
           
           string decryptedText = System.Text.Encoding.UTF8.GetString(decrypted);
           Console.WriteLine($"Расшифрованный текст: {decryptedText}");
           Console.WriteLine($"Данные совпадают: {originalText == decryptedText}");
           
           // 3.5. Шифрование в режиме CFB (Cipher Feedback)
           Console.WriteLine("\n[3.5] Шифрование данных (режим CFB)...");
           cipher.Mode = CipherMode.CFB;
           cipher.Padding = PaddingMode.PKCS7;
           
           byte[] encryptedCfb;
           using (var encryptor = cipher.CreateEncryptor())
           using (var ms = new MemoryStream())
           using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
           {
               cs.Write(data, 0, data.Length);
               cs.FlushFinalBlock();
               encryptedCfb = ms.ToArray();
           }
           
           Console.WriteLine($"Зашифрованные данные (CFB): {BitConverter.ToString(encryptedCfb).Replace("-", "")}");
           
           // 3.6. Неправильное дешифрование (с другим IV)
           Console.WriteLine("\n[3.6] Попытка дешифрования с неверным IV...");
           try
           {
               cipher.IV = new byte[cipher.IV.Length]; // Обнуляем IV
               using (var decryptor = cipher.CreateDecryptor())
               using (var ms = new MemoryStream(encrypted))
               using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
               using (var output = new MemoryStream())
               {
                   cs.CopyTo(output);
                   byte[] wrongDecrypted = output.ToArray();
                   Console.WriteLine("⚠ Ожидалась ошибка, но данные были расшифрованы!");
               }
           }
           catch (CryptographicException ex)
           {
               Console.WriteLine($"✅ Ожидаемая ошибка дешифрования: {ex.Message}");
           }
       }
   }
   /// <summary>
   /// Демонстрация асимметричных операций: шифрование и подпись
   /// </summary>
   private static void DemonstrateAsymmetricOperations()
   {
       Console.WriteLine("\n=== 4. АСИММЕТРИЧНЫЕ ОПЕРАЦИИ (ГОСТ Р 34.10-2012) ===");
       
       // 4.1. Получаем сертификат
       Console.WriteLine("\n[4.1] Поиск сертификата ГОСТ Р 34.10-2012...");
       var cert = GetGostCertificate();
       
       Console.WriteLine($"Сертификат: {cert.SubjectName.Name}");
       Console.WriteLine($"Алгоритм: {cert.PublicKey.Oid.FriendlyName}");
       Console.WriteLine($"Размер ключа: {GetKeySize(cert)} бит");
       Console.WriteLine($"Действителен до: {cert.NotAfter}");
       
       if (!cert.HasPrivateKey)
       {
           Console.WriteLine("⚠ Внимание: сертификат не содержит закрытого ключа. Некоторые операции будут недоступны.");
       }
       // 4.2. Подготовка данных
       byte[] data = System.Text.Encoding.UTF8.GetBytes("Важные данные для подписи и шифрования");
       Console.WriteLine($"\n[4.2] Тестовые данные ({data.Length} байт):");
       Console.WriteLine(BitConverter.ToString(data).Replace("-", ""));
       // 4.3. Создание и проверка подписи
       if (cert.HasPrivateKey)
       {
           Console.WriteLine("\n[4.3] Создание и проверка электронной подписи...");
           CreateAndVerifySignature(cert, data);
       }
       else
       {
           Console.WriteLine("\n[4.3] Пропуск создания подписи (нет закрытого ключа)");
       }
       // 4.4. Асимметричное шифрование
       Console.WriteLine("\n[4.4] Асимметричное шифрование...");
       AsymmetricEncryptionDemo(cert, data);
   }
   /// <summary>
   /// Получение сертификата ГОСТ Р 34.10-2012
   /// </summary>
   private static X509Certificate2 GetGostCertificate()
   {
       var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
       store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
       
       try
       {
           // OID для ГОСТ Р 34.10-2012 (256 бит)
           const string GOST_3410_2012_256_OID = "1.2.643.7.1.1.1.1";
           // OID для ГОСТ Р 34.10-2012 (512 бит)
           const string GOST_3410_2012_512_OID = "1.2.643.7.1.1.1.2";
           
           // Ищем сертификат с закрытым ключом
           foreach (var cert in store.Certificates)
           {
               if ((cert.PublicKey.Oid.Value == GOST_3410_2012_256_OID || 
                    cert.PublicKey.Oid.Value == GOST_3410_2012_512_OID) &&
                   cert.NotAfter >= DateTime.Now &&
                   cert.HasPrivateKey)
               {
                   return cert;
               }
           }
           
           // Если не нашли с закрытым ключом, берем любой подходящий
           foreach (var cert in store.Certificates)
           {
               if ((cert.PublicKey.Oid.Value == GOST_3410_2012_256_OID || 
                    cert.PublicKey.Oid.Value == GOST_3410_2012_512_OID) &&
                   cert.NotAfter >= DateTime.Now)
               {
                   return cert;
               }
           }
           
           throw new Exception("Не найден действительный сертификат ГОСТ Р 34.10-2012");
       }
       finally
       {
           store.Close();
       }
   }
   /// <summary>
   /// Определение размера ключа сертификата
   /// </summary>
   private static int GetKeySize(X509Certificate2 cert)
   {
       return cert.PublicKey.Oid.Value switch
       {
           "1.2.643.7.1.1.1.1" => 256, // ГОСТ Р 34.10-2012 (256 бит)
           "1.2.643.7.1.1.1.2" => 512, // ГОСТ Р 34.10-2012 (512 бит)
           _ => throw new Exception("Неизвестный алгоритм ключа")
       };
   }
   /// <summary>
   /// Создание и проверка электронной подписи
   /// </summary>
   private static void CreateAndVerifySignature(X509Certificate2 cert, byte[] data)
   {
       // Выбираем алгоритм хеширования в зависимости от сертификата
       using Gost_R3411_HashAlgorithm hashAlg = cert.PublicKey.Oid.Value switch
       {
           "1.2.643.7.1.1.1.1" => new Gost_R3411_2012_256_HashAlgorithm(), // 256 бит
           "1.2.643.7.1.1.1.2" => new Gost_R3411_2012_512_HashAlgorithm(), // 512 бит
           _ => throw new Exception("Неизвестный алгоритм ключа")
       };
       
       // Вычисляем хеш
       byte[] hash = hashAlg.ComputeHash(data);
       Console.WriteLine($"Хеш ({hashAlg.GetType().Name}): {BitConverter.ToString(hash).Replace("-", "")}");
       // Создаем подпись
       byte[] signature;
       using (var privateKey = cert.GetPrivateKeyAlgorithm() as Gost_R3410_2012_AsymmetricAlgorithm)
       {
           if (privateKey == null)
               throw new Exception("Не удалось получить алгоритм подписи из сертификата");
           
           signature = privateKey.CreateSignature(hash);
           Console.WriteLine($"\nПодпись ({signature.Length} байт):");
           Console.WriteLine(BitConverter.ToString(signature).Replace("-", ""));
       }
       // Проверяем подпись
       using (var publicKey = cert.GetPublicKeyAlgorithm() as Gost_R3410_2012_AsymmetricAlgorithm)
       {
           if (publicKey == null)
               throw new Exception("Не удалось получить алгоритм проверки из сертификата");
           
           bool isValid = publicKey.VerifySignature(hash, signature);
           Console.WriteLine($"\nПроверка подписи: {(isValid ? "✅ УСПЕШНО" : "❌ ОШИБКА")}");
           
           // Проверка с измененными данными
           byte[] modifiedData = (byte[])data.Clone();
           modifiedData[0] ^= 0xFF;
           byte[] modifiedHash = hashAlg.ComputeHash(modifiedData);
           bool isModifiedValid = publicKey.VerifySignature(modifiedHash, signature);
           Console.WriteLine($"Проверка с измененными данными: {(isModifiedValid ? "❌ ОШИБКА" : "✅ УСПЕШНО")}");
       }
   }
   /// <summary>
   /// Демонстрация асимметричного шифрования
   /// </summary>
   private static void AsymmetricEncryptionDemo(X509Certificate2 cert, byte[] data)
   {
       // Получаем публичный ключ для шифрования
       using (var publicKey = cert.GetPublicKeyAlgorithm() as Gost_R3410_2012_AsymmetricAlgorithm)
       {
           if (publicKey == null)
               throw new Exception("Не удалось получить алгоритм шифрования из сертификата");
           
           // Шифруем данные
           Console.WriteLine("\n[4.4.1] Шифрование данных открытым ключом...");
           byte[] encrypted = publicKey.EncryptData(data);
           Console.WriteLine($"Зашифрованные данные ({encrypted.Length} байт):");
           Console.WriteLine(BitConverter.ToString(encrypted).Replace("-", ""));
           // Если есть приватный ключ, расшифровываем
           if (cert.HasPrivateKey)
           {
               Console.WriteLine("\n[4.4.2] Дешифрование данных закрытым ключом...");
               using (var privateKey = cert.GetPrivateKeyAlgorithm() as Gost_R3410_2012_AsymmetricAlgorithm)
               {
                   if (privateKey == null)
                       throw new Exception("Не удалось получить алгоритм дешифрования из сертификата");
                   
                   byte[] decrypted = privateKey.DecryptData(encrypted);
                   Console.WriteLine($"Расшифрованные данные: {BitConverter.ToString(decrypted).Replace("-", "")}");
                   Console.WriteLine($"Данные совпадают: {data.SequenceEqual(decrypted)}");
               }
           }
           else
           {
               Console.WriteLine("\n[4.4.2] Пропуск дешифрования (нет закрытого ключа)");
           }
       }
   }
}

Полное описание возможностей ГОСТ-криптографии 2012

1. Хеширование (ГОСТ Р 34.11-2012)

Алгоритмы:

ГОСТ Р 34.11-2012 (256 бит) - используется для электронной подписи с 256-битными ключами

ГОСТ Р 34.11-2012 (512 бит) - используется для электронной подписи с 512-битными ключами

Особенности:

Размер блока: 512 бит

Размер хеша: 256 или 512 бит

Устойчивость к коллизиям

Оптимизирован для 64-битных процессоров

Применение:

Проверка целостности данных

Создание электронной подписи

Генерация ключей

2. Симметричное шифрование (ГОСТ 28147-89)

Характеристики:

Размер ключа: 256 бит

Размер блока: 64 бит

Режимы работы: ECB, CBC, CFB, OFB, CTR

Особенности:

32 раунда преобразований

Использует S-блоки (таблицы замен)

Поддерживает различные режимы заполнения (Padding)

Применение:

Шифрование конфиденциальных данных

Защита каналов связи

Шифрование файлов

3. Асимметричное шифрование (ГОСТ Р 34.10-2012)

Алгоритмы:

ГОСТ Р 34.10-2012 (256 бит) - на эллиптических кривых

ГОСТ Р 34.10-2012 (512 бит) - на эллиптических кривых

Особенности:

Основан на эллиптической криптографии

Использует параметры стандартных эллиптических кривых

Обеспечивает стойкость к квантовым атакам

Применение:

Электронная подпись

Шифрование ключей

Аутентификация

4. Электронная подпись (ГОСТ Р 34.10-2012)

Процесс создания подписи:

Вычисление хеша данных (ГОСТ Р 34.11-2012)

Генерация подписи с использованием закрытого ключа

Проверка подписи с использованием открытого ключа

Особенности:

Поддерживает детерминированную и случайную подпись

Обеспечивает неотказуемость

Интегрирована с инфраструктурой PKI

Рекомендации по использованию

Безопасность ключей:

Никогда не храните закрытые ключи в открытом виде

Используйте защищенные хранилища ключей

Регулярно обновляйте ключи

Выбор алгоритмов:

Для новых проектов используйте только алгоритмы 2012 года

Для высокой безопасности выбирайте 512-битные варианты

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

Обработка ошибок:

Всегда проверяйте результат операций

Обрабатывайте все исключения

Ведение журнала криптографических операций

Производительность:

Для больших данных используйте гибридное шифрование

Кешируйте результаты хеширования

Параллелизуйте операции при возможности

Этот код демонстрирует все основные возможности ГОСТ-криптографии 2012 года и может служить основой для разработки защищенных приложений в .NET.