AES-CTR возвращает нешифрованный массив байтов - PullRequest
0 голосов
/ 21 февраля 2020

Я сейчас учусь в университете, мой профессор сказал мне, чтобы внедрить шифрование файлов с помощью 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);
}
...