CryptGenKey
CryptGenKey — это функция Windows CryptoAPI (Cryptographic Application Programming Interface), предназначенная для генерации криптографических ключей. Она входит в состав библиотеки advapi32.dll и используется для создания ключей симметричного и асимметричного шифрования, а также ключей для хеширования и электронной подписи в операционных системах семейства Microsoft Windows.
История и контекст
Функция CryptGenKey была введена в Windows 2000 как часть расширения CryptoAPI 2.0. В более ранних версиях Windows (Windows 95, 98, NT 4.0) использовалась устаревшая функция CryptGenKey из CryptoAPI 1.0, которая имела ограниченные возможности и не поддерживала современные алгоритмы. В Windows Vista и более поздних версиях функция была дополнена поддержкой новых криптографических стандартов, включая AES, ECC (эллиптическую криптографию) и алгоритмы для работы с сертификатами X.509.
С появлением Windows 8 и Windows Server 2012 Microsoft начала постепенно заменять CryptoAPI на более современную платформу Cryptography Next Generation (CNG), однако CryptGenKey остаётся доступной для обратной совместимости. В Windows 10 и Windows 11 функция по-прежнему поддерживается, но для новых разработок рекомендуется использовать CNG-функции, такие как BCryptGenerateKeyPair или NCryptCreatePersistedKey.
Синтаксис и параметры
Функция объявляется в заголовочном файле wincrypt.h и имеет следующий прототип на языке C:
``c BOOL CryptGenKey( HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey ); ``
Параметры:
- hProv — дескриптор криптопровайдера (CSP), полученный через
CryptAcquireContext. Определяет, какой поставщик криптографических услуг (например, Microsoft Base Cryptographic Provider или Microsoft Enhanced Cryptographic Provider) будет использоваться. - Algid — идентификатор алгоритма (ALG_ID). Определяет тип генерируемого ключа: симметричный (CALG_AES_128, CALG_3DES), асимметричный (CALG_RSA_KEYX, CALG_DH_EPHEM) или ключ для хеширования (CALG_MD5, CALG_SHA1). Для алгоритмов с переменной длиной ключа необходимо указывать конкретный размер через флаги.
- dwFlags — флаги, управляющие генерацией. Наиболее важные:
CRYPT_EXPORTABLE— ключ может быть экспортирован (сохранён или передан другому приложению).CRYPT_CREATE_SALT— к ключу добавляется случайная соль для защиты от атак по словарю.CRYPT_USER_PROTECTED— запрашивает подтверждение пользователя (например, через диалоговое окно) при использовании ключа.CRYPT_ARCHIVABLE— ключ может быть архивирован (экспортирован с сохранением метаданных).CRYPT_PREGEN— для асимметричных алгоритмов генерирует только часть ключа (например, только открытый ключ).- phKey — указатель на переменную, которая при успешном вызове получает дескриптор сгенерированного ключа.
Возвращаемое значение: TRUE при успехе, FALSE при ошибке. Код ошибки можно получить через GetLastError.
Процесс генерации ключей
Симметричные ключи
Для симметричных алгоритмов (AES, 3DES, RC2, RC4) CryptGenKey генерирует случайную последовательность битов заданной длины. Длина ключа определяется флагом dwFlags или параметрами криптопровайдера. Например, для AES-128 ключ имеет длину 128 бит (16 байт). Генерация использует криптостойкий генератор псевдослучайных чисел (CSPRNG), реализованный в провайдере. В Microsoft Enhanced Cryptographic Provider используется алгоритм на основе хеш-функции SHA-1.
Асимметричные ключи
Для асимметричных алгоритмов (RSA, DSA, Diffie-Hellman) функция генерирует пару ключей: открытый и закрытый. Закрытый ключ хранится внутри криптопровайдера и не может быть извлечён в открытом виде (если не установлен флаг CRYPT_EXPORTABLE). Открытый ключ может быть экспортирован через CryptExportKey. Генерация асимметричных ключей требует больше времени, так как включает поиск больших простых чисел (для RSA) или вычисление дискретных логарифмов (для DSA).
Ключи для хеширования
Для алгоритмов хеширования (MD5, SHA-1, SHA-256) CryptGenKey не генерирует ключ в традиционном смысле. Вместо этого создаётся дескриптор, который используется для инициализации хеш-объекта через CryptCreateHash. Фактически, ключ для хеширования — это пустой объект, к которому затем добавляются данные.
Безопасность и ограничения
CryptGenKey считается устаревшей функцией в контексте современной криптографии. Основные недостатки:
- Зависимость от криптопровайдера: качество генерации ключа зависит от реализации CSP. Некоторые сторонние провайдеры могут использовать слабые генераторы случайных чисел.
- Отсутствие поддержки современных алгоритмов: функция не поддерживает алгоритмы на основе эллиптических кривых (ECDSA, ECDH) в режиме CryptoAPI. Для этого требуется CNG.
- Управление ключами: ключи хранятся в контейнерах провайдера, что может быть неудобно для распределённых систем.
- Проблемы с экспортом: при использовании флага
CRYPT_EXPORTABLEключ может быть скопирован злоумышленником, если система скомпрометирована.
В Windows 10 и Windows 11 Microsoft рекомендует использовать CNG-функции, такие как BCryptGenerateSymmetricKey или BCryptGenerateKeyPair, которые обеспечивают более высокую производительность и совместимость с современными стандартами (FIPS 140-2, Suite B).
Пример использования
Ниже приведён фрагмент кода на C++, демонстрирующий генерацию 128-битного ключа AES:
```cpp
include <windows.h>
include <wincrypt.h>
include <iostream>
int main() { HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0;
// Получение дескриптора криптопровайдера if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { std::cerr << "CryptAcquireContext failed: " << GetLastError() << std::endl; return 1; }
// Генерация ключа AES-128 if (!CryptGenKey(hProv, CALG_AES_128, CRYPT_EXPORTABLE, &hKey)) { std::cerr << "CryptGenKey failed: " << GetLastError() << std::endl; CryptReleaseContext(hProv, 0); return 1; }
std::cout << "Key generated successfully." << std::endl;
// Освобождение ресурсов CryptDestroyKey(hKey); CryptReleaseContext(hProv, 0); return 0; } ```
Альтернативы и современные аналоги
В современных версиях Windows CryptGenKey заменяется следующими функциями CNG:
- BCryptGenerateSymmetricKey — для симметричных алгоритмов (AES, 3DES).
- BCryptGenerateKeyPair — для асимметричных алгоритмов (RSA, DSA, ECDSA, ECDH).
- NCryptCreatePersistedKey — для создания ключей, хранящихся в защищённом хранилище (например, TPM или смарт-карта).
Для кроссплатформенной разработки рекомендуется использовать библиотеки OpenSSL, LibreSSL или Bouncy Castle, которые предоставляют аналогичную функциональность.
Применение
CryptGenKey широко использовалась в приложениях Windows до середины 2010-х годов для:
- Шифрования файлов и данных (например, в EFS — Encrypting File System).
- Создания цифровых подписей (в компонентах Authenticode).
- Защиты сетевых соединений (в старых версиях SSL/TLS).
- Хранения паролей и ключей в реестре.
В настоящее время функция применяется в основном в устаревших приложениях и для обратной совместимости. Новые разработки должны использовать CNG.
Интересные факты
- CryptGenKey может генерировать ключи длиной до 16 384 бит для RSA (при использовании Microsoft Enhanced Cryptographic Provider).
- В Windows XP функция поддерживала алгоритм RC4 с длиной ключа до 128 бит, который сейчас считается небезопасным.
- При вызове с флагом
CRYPT_USER_PROTECTEDна некоторых системах может появиться диалоговое окно с запросом на использование ключа, что замедляет работу приложения. - Функция не поддерживает генерацию ключей для алгоритмов ГОСТ (ГОСТ 28147-89, ГОСТ Р 34.10-2012) в стандартной поставке Windows. Для этого требуется установка сторонних криптопровайдеров, например, от компании «КриптоПро».
Источники
- Microsoft Docs: CryptGenKey function (Windows) — официальная документация.
- Microsoft Docs: Cryptography API (CryptoAPI) — обзор CryptoAPI.
- Microsoft Docs: Cryptography Next Generation (CNG) — описание CNG.
- Schneier B. Applied Cryptography, 2nd ed. — John Wiley & Sons, 1996.
- RFC 8017: PKCS #1: RSA Cryptography Specifications Version 2.2.
- FIPS PUB 197: Advanced Encryption Standard (AES).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →