0)); // Флаги
Симметричное шифрование
Начало работы по симметричному шифрованию происходит аналогично началу работы с функциями хэширования: необходимо создать и подготовить симметричный ключ и буфер его объекта путем создания соответствующего поставщика алгоритма, определения размера буфера и его выделения. При обращении к функции BCryptGenerateSymmetricKey с использованием секретных данных создается симметричный ключ:
BCRYPT_KEY_HANDLE key = 0;
NT_VERIFY(::BCryptGenerateSymmetricKey(algorithmProvider, //поставщик алгоритмов, реализующий алгоритм симметричного шифрования
&key, //дескриптор объекта ключа
keyBuffer.GetData(), //буфер ключа
keyBuffer.GetSize(), //размер буфера ключа
secret.GetData(), //буфер, содержащий секретный ключ
secret.GetSize(), //размер буфера с секретным ключом
0)); // Флаги
По завершении работы с объектом ключа необходимо уничтожить его с помощью функции BCryptDestroyKey, а затем освободить буфер объекта ключа.
Для шифрования и расшифровывания данных для симметричного и асимметричного ключа используются соответственно функции BCryptEncrypt и BCryptDecrypt. Эти функции используются одинаково, независимо от применяемого типа ключа. В процессе симметричного шифрования отправитель и получатель должны использовать несколько общих свойств в режиме совместного доступа, а именно: ключ, созданный посредством одного и того же секретного значения и совпадающие значения свойств, одинаковые вектора инициализации, одинаковое заполнение.
Сначала требуется определить размер блока данных для алгоритма с помощью известной уже функции BCryptGetProperty (key, BCRYPT_BLOCK_LENGTH,…).
Затем, по окончании подготовки шифруемого сообщения и вектора инициализации, вызывается функция BCryptEncrypt для шифрования открытого текста сообщения, определив сперва размер буфера, в который будет поступать зашифрованный текст:
ULONG ciphertextSize = 0;
NT_VERIFY(::BCryptEncrypt(key, //ключ для шифрования
message.GetData(), //данные шифруемого сообщения
message.GetSize(), //размер шифруемого сообщения
0, // доп. информация о заполнении для асимметричного шифрования
iv.GetData(), //буфер вектора инициализации
iv.GetSize(), //размер буфера
0, // буфер для зашифрованного текста
0, // размер буфера
&ciphertextSize, //размер предполагаемого зашифрованного текста
0)); // флаги
После этого приступаем к созданию буфера для зашифрованного текста и снова вызываем функцию BCryptEncrypt:
Buffer ciphertext;
NT_VERIFY(ciphertext.Create(ciphertextSize));
NT_VERIFY(::BCryptEncrypt(key,
message.GetData(),
message.GetSize(),
0,
iv.GetData(),
iv.GetSize(),
ciphertext.GetData(),
ciphertext.GetSize(),
&ciphertextSize,
0));
Процесс расшифровки совпадает во многом с процессом шифрования. Если размер расшифрованного текста заранее не известен, то вызывается функция BCryptDecrypt практически аналогичным способом, описанным ранее для определения размера зашифрованного текста. И, наконец, вызывается функция BCryptDecrypt с зашифрованным текстом, вектором инициализации и буфером расшифрованного текста для результирующего сообщения:
Buffer plaintext;
NT_VERIFY(plaintext.Create(plaintextSize));
NT_VERIFY(::BCryptDecrypt(newKey,
ciphertext.GetData(),
ciphertext.GetSize(),
0,
iv.GetData(),
iv.GetSize(),
plaintext.GetData(),
plaintext.GetSize(),
&plaintextSize,
0));
Нужно не забыть, что при процессе расшифровывания необходимо указать те же флаги, которые использовались при шифровании текста.
Асимметричное шифрование
Используется подход с применением открытого ключа, в котором обе стороны поддерживают открытый и закрытый ключи, причем закрытый ключ используется для расшифровки данных, а шифрование происходит с помощью доступного всем открытого ключа.
Минус такого типа шифрования состоит в том, что оно является более дорогостоящим по сравнению с симметричным, однако, является незаменимым при установлении взаимодействия с предоставлением сторонам механизма безопасного совместного использования информации о ключе симметричного шифрования.
Генерация пары открытого и закрытого ключей возможна с помощью функции BCryptGenerateKeyPair:
NT_VERIFY(::BCryptGenerateKeyPair(algorithmProvider,
&key, keySize, //дескриптор объекта ключа и размер объекта
