Я сейчас учусь в университете, мой профессор сказал мне, чтобы внедрить шифрование файлов с помощью AES-CTR. Я выбрал C ++ для этого и нашел библиотеку от github - TineAES. Это небольшая реализация AES (ECB, CB C, CTR). Я использую это для шифрования массива байтов.
Вот моя переписанная функция для шифрования (мне не нужна структура для хранения ключа и одноразового номера)
void AES_CTR_xcrypt_buffer(uint8_t* buf, uint32_t length, uint8_t* key, uint8_t* iv)
{
uint8_t RoundKey[176];
KeyExpansion(RoundKey, key);
uint8_t buffer[AES_BLOCKLEN];
unsigned i;
int bi;
for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
{
if (bi == AES_BLOCKLEN)
{
CopyMemory(buffer, iv, AES_BLOCKLEN);
Cipher((state_t*)buffer, RoundKey);
for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
{
if (iv[bi] == 255)
{
iv[bi] = 0;
continue;
}
iv[bi] += 1;
break;
}
bi = 0;
}
buf[i] = (buf[i] ^ buffer[bi]);
}
}
Прежде всего, я генерирую безопасный ключ и одноразовый номер для этого файла. Затем я читаю все данные из файла, используя ReadFile();
. После этого я использую свою функцию для шифрования байтов и записи ключа и одноразового номера в конец файла (мне не нужно сохранять его в безопасности, как сказал мне мой профессор).
Моя функция шифрования файлов:
void EncryptFileWithSecureKey(LPCWSTR filePath)
{
BYTE* aes_key_dec = (BYTE*)HeapAlloc(GetProcessHeap(), NULL, 44);
GenerateUnicKey(aes_key_dec);
BYTE* aes_iv_dec = (BYTE*)HeapAlloc(GetProcessHeap(), NULL, 44);
GenerateUnicKey(aes_iv_dec);
HANDLE hFile;
DWORD dwBytesRead, dwBytesWritten, dwPos;
LARGE_INTEGER dist;
if (hFile = CreateFileW(filePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL))
{
LARGE_INTEGER size;
GetFileSizeEx(hFile, &size);
DWORD lenght = size.QuadPart;
BYTE* buff = (BYTE*)HeapAlloc(GetProcessHeap(), NULL, lenght);
dist.QuadPart = 0;
dwPos = SetFilePointerEx(hFile, dist, nullptr, FILE_BEGIN);
ReadFile(hFile, buff, lenght, &dwBytesRead, NULL);
AES_CTR_xcrypt_buffer(buff, lenght, aes_key_dec, aes_iv_dec);
dwPos = SetFilePointerEx(hFile, dist, nullptr, FILE_BEGIN);
WriteFile(hFile, buff, lenght, &dwBytesWritten, NULL);
HeapFree(GetProcessHeap(), NULL, buff);
dist.QuadPart = size.QuadPart;
dwPos = SetFilePointerEx(hFile, dist, nullptr, FILE_BEGIN);
WriteFile(hFile, aes_key_dec, 44, &dwBytesWritten, NULL);
dist.QuadPart = size.QuadPart + 44;
dwPos = SetFilePointerEx(hFile, dist, nullptr, FILE_BEGIN);
WriteFile(hFile, aes_iv_dec, 44, &dwBytesWritten, NULL);
}
CloseHandle(hFile);
}
В результате я всегда получаю зашифрованный массив.
Теперь проблема.
Функция расшифровки моего файла:
void RestoreFile(LPCWSTR filePath)
{
HANDLE hFile;
DWORD dwBytesRead, dwBytesWritten, dwPos;
if (hFile = CreateFileW(filePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))
{
LARGE_INTEGER size, dist;
GetFileSizeEx(hFile, &size);
BYTE* aes_key_dec = (BYTE*)HeapAlloc(GetProcessHeap(), NULL, 44);
BYTE* aes_iv_dec = (BYTE*)HeapAlloc(GetProcessHeap(), NULL, 44);
dist.QuadPart = size.QuadPart - 44 - 44;
dwPos = SetFilePointerEx(hFile, dist, nullptr, FILE_BEGIN);
ReadFile(hFile, aes_key_dec, 44, &dwBytesRead, NULL);
dist.QuadPart = size.QuadPart - 44;
dwPos = SetFilePointerEx(hFile, dist, nullptr, FILE_BEGIN);
ReadFile(hFile, aes_iv_dec, 44, &dwBytesRead, NULL);
dist.QuadPart = size.QuadPart - 44 - 44;
dwPos = SetFilePointerEx(hFile, dist, nullptr, FILE_BEGIN);
SetEndOfFile(hFile);
GetFileSizeEx(hFile, &size);
DWORD lenght = size.QuadPart;
BYTE* buff = (BYTE*)HeapAlloc(GetProcessHeap(), NULL, lenght);
dist.QuadPart = 0;
dwPos = SetFilePointerEx(hFile, dist, nullptr, FILE_BEGIN);
ReadFile(hFile, buff, lenght, &dwBytesRead, NULL);
AES_CTR_xcrypt_buffer(buff, lenght, aes_key_dec, aes_iv_dec);
dwPos = SetFilePointerEx(hFile, dist, nullptr, FILE_BEGIN);
WriteFile(hFile, buff, lenght, &dwBytesWritten, NULL);
HeapFree(GetProcessHeap(), NULL, buff);
CloseHandle(hFile);
}
}
После этой функции я получаю не дешифрованный файл. Просто некоторые персонажи unicdoe.
Насколько я знаю, AES-CTR использует ту же функцию для шифрования и дешифрования. Итак, что за жалость? Ключ и nonce верны, функция та же самая ...
PS моя функция генерации ключа:
void GenerateUnicKey(BYTE* data)
{
HCRYPTKEY hKey;
DWORD len = 0;
if (!CryptGenKey(hProvs, CALG_AES_256, CRYPT_EXPORTABLE, &hKey))
{
ExitProcess(0);
}
if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, NULL, &len))
{
ExitProcess(0);
}
if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, data, &len))
{
ExitProcess(0);
}
CryptDestroyKey(hKey);
}