Итак, у меня есть 5 файлов, которые я шифрую. Я не устанавливаю IV.
Первый файл расшифровывается нормально,
тогда первый блок из оставшихся файлов не расшифровывается.
Таким образом, файлы расшифровывают 99%.
Я попытался установить IV на статическое значение и случайное значение, тот же результат.
Первый файл, который я зашифровал, НЕ обязательно должен быть первым файлом, который я расшифровал, чтобы он был расшифрован на 100%.
Что заставляет меня верить, что это связано с расшифровкой?
Поэтому для шифрования я импортирую ключ aes, чтобы создать дескриптор ключа.
затем я шифрую файл и перемещаюсь к другому файлу, используя ту же самую ручку ключа …
Должен ли я иметь новый дескриптор ключа для каждого файла ..?
Есть ли функция для очистки ручки ключа?
Что-то говорит мне, что WCAPI использует последний блок последнего файла в качестве IV для следующего файла?
прости меня, если я что-то неправильно понимаю.
Вот функция decrypt_file:
DWORD dwMode = CRYPT_MODE_CBC;
LPVOID aes_key = NULL;
LPVOID tmp_blk_buff = NULL;
DWORD bytes_read = NULL;
BOOL eof = FALSE;
DWORD tmp_blk_buff_size = TMP_BLOCK_BUFFER_SIZE(context->in_size);
tmp_blk_buff = VirtualAlloc(0, tmp_blk_buff_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
Utils::zero_mem(tmp_blk_buff, tmp_blk_buff_size);
LPVOID iv_ = NULL;
iv_ = VirtualAlloc(0, AES_BLOCK_SIZE_, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
Utils::zero_mem(iv_, AES_BLOCK_SIZE_);
/*BYTE iv[AES_BLOCK_SIZE_] = {
0xAD, 0xAD, 0xAD, 0xAD,
0xAD, 0xAD, 0xAD, 0xAD,
0xAD, 0xAD, 0xAD, 0xAD,
0xAD, 0xAD, 0xAD, 0xAD
};
*/
// Utils::copy_mem(iv_, AES_BLOCK_SIZE_, iv, AES_BLOCK_SIZE_);//CryptSetKeyParam(context->aes_hKey, KP_IV, (BYTE*)&iv_, 0);
CryptSetKeyParam(context->aes_hKey, KP_MODE, (BYTE*)&dwMode, 0);
// Encrypt data
do{
Utils::zero_mem(tmp_blk_buff, tmp_blk_buff_size);
bytes_read = NULL;
ReadFile(hFile_in, tmp_blk_buff, AES_BLOCK_SIZE_, &bytes_read, NULL);
if (bytes_read < AES_BLOCK_SIZE_)
{
eof = TRUE;
}
if (!CryptDecrypt(context->aes_hKey, NULL, eof, 0,(LPBYTE)tmp_blk_buff, &bytes_read))
{
context->last_error = GetLastError();
eof = TRUE;
}
WriteFile(hFile_out, tmp_blk_buff, bytes_read, &bytes_read, NULL);
} while (!eof);
// ===============
// Zero and Free Allocated memory.
Utils::zero_mem(tmp_blk_buff, tmp_blk_buff_size);
VirtualFree(tmp_blk_buff, tmp_blk_buff_size, MEM_RELEASE);
return (DWORD)1;
Да, это говорит о том, что у вас есть разные значения для данной пары шифрования / дешифрования.
Причина, по которой «поврежден» только первый блок, состоит в том, что ошибки блока CBC распространяются только на следующий блок (и не далее).
Вы либо используете цепочку из предыдущей операции (если вы повторно используете контекст в файлах), либо вы не инициализируете контекст одним и тем же значением как для шифрования, так и для дешифрования.
Глядя на свой код, вы закомментировали CryptSetKeyParam(....,KP_IV,....)
Это означает, что ваш контекст AES, вероятно, содержит неизвестные данные в IV.
Относительно распространенной практикой всегда является использование 0 для IV, но в начале данных помещается блок случайной «соли». Затем вы игнорируете первый блок данных при расшифровке. Это только для рандомизации данных.
ИЛИ, вы можете рандомизировать IV, но отправить его в зашифрованном виде в виде простого текста. Это тоже очень распространено.
Или вы можете рандомизировать IV при шифровании, поместить блок случайных данных перед реальным сообщением. Используйте любой IV для расшифровки и выбросьте этот первый блок (потому что это будет мусор).
Это все в значительной степени один и тот же результат (в итоге вы передаете 16 байтов в качестве служебных данных), но вы должны добавить некоторую случайность в свое сообщение (либо через IV, либо через первый блок), чтобы предотвратить короткие атаки.
Я использовал CryptDuplicateKey с соответствующим вызовом DestroyKey, что решило мои проблемы.
Использование дублированного ключа для установки параметров, оставляя исходный ключ без изменений.