Полное руководство по использованию ГОСТ-криптографии в .NET
В этом подробном руководстве я покажу использование всех основных криптографических алгоритмов ГОСТ 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.
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.