У меня есть небольшая программа, которая шифрует файлы с помощью ключа AES-256. Ключ, используемый для шифрования файла, генерируется случайным образом.
Программа шифрования выглядит следующим образом:
- Получить криптографический контекст -
CryptAcquireContext
- сгенерируйте ключ AES-256, используя
CryptGenKey
- Зашифровать файл с помощью этого ключа -
CryptEncrypt
- Освободить критоконтекст -
CryptReleaseContext
Зашифрованный файл представляет собой небольшой test.txt
файл, содержащий строку: «просто тест». Итак, необработанные шестнадцатеричные байты в файле:
6A 75 73 74 20 61 20 74 65 73 74
Ключ AES-256, используемый для шифрования в шестнадцатеричном формате:
3f10e23bb1a5dfd9c8ca06195e43043386a9ba4c63c35ac518f463ba768f001b
Зашифрованный файл test.enc
имеет байты:
C8 B5 92 51 22 53 75 A1 34 80 EC AA 37 1C 6C BE
Вопрос:
Как мне написать программу на c / c ++ для расшифровки этих байтов с помощью шестнадцатеричного ключа AES-256 с помощью функции CryptDecrypt
Windows CryptoAPI?
Что я пробовал:
Я написал следующую программу дешифрования (небольшое изменение здесь .)
#include <Windows.h>
#include <wincrypt.h>
#include <stdio.h>
#pragma comment(lib, "crypt32.lib")
#define BLOCK_LEN 128
HCRYPTPROV hCryptProv;
int wmain(int argc, wchar_t* argv[])
{
wchar_t default_key[] = L"PxDiO7Gl39nIygYZXkMEM4apukxjw1rFGPRjunaPABs";
wchar_t* key_str = default_key;
size_t len = lstrlenW(key_str);
if (!CryptAcquireContext(
&hCryptProv,
NULL,
MS_ENH_RSA_AES_PROV,
PROV_RSA_AES,
NULL))
{
/*std::cout << "error acquiring context\n";
std::cout << GetLastErrorAsString();*/
exit(1);
}
HCRYPTKEY hKey;
wchar_t* filename = argv[1];
wchar_t* filename2 = argv[2];
printf("Key: %S\n", key_str);
printf("Key len: %#x\n", len);
printf("Input File: %S\n", filename);
printf("Output File: %S\n", filename2);
printf("----\n");
HANDLE hInpFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hInpFile == INVALID_HANDLE_VALUE) {
printf("Cannot open input file!\n");
system("pause");
return (-1);
}
printf("\nEncrypted file read.");
HANDLE hOutFile = CreateFileW(filename2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOutFile == INVALID_HANDLE_VALUE) {
printf("Cannot open output file!\n");
system("pause");
return (-1);
}
printf("\nDecryption file created.");
DWORD dwStatus = 0;
BOOL bResult = FALSE;
wchar_t info[] = L"Microsoft Enhanced RSA and AES Cryptographic Provider";
/*BOOL CryptDeriveKey(
HCRYPTPROV hProv,
ALG_ID Algid,
HCRYPTHASH hBaseData,
DWORD dwFlags,
HCRYPTKEY * phKey
);*/
HCRYPTHASH hHash;
if (!CryptCreateHash(hCryptProv, CALG_SHA_256, 0, 0, &hHash)) {
dwStatus = GetLastError();
printf("CryptCreateHash failed: %x\n", dwStatus);
CryptReleaseContext(hCryptProv, 0);
system("pause");
return dwStatus;
}
if (!CryptHashData(hHash, (BYTE*)key_str, len, 0)) {
DWORD err = GetLastError();
printf("CryptHashData Failed : %#x\n", err);
system("pause");
return (-1);
}
printf("[+] CryptHashData Success\n");
if (!CryptDeriveKey(hCryptProv, CALG_AES_256, hHash, 0, &hKey)) {
dwStatus = GetLastError();
printf("CryptDeriveKey failed: %x\n", dwStatus);
CryptReleaseContext(hCryptProv, 0);
system("pause");
return dwStatus;
}
printf("[+] CryptDeriveKey Success\n");
const size_t chunk_size = BLOCK_LEN;
BYTE chunk[chunk_size] = { 0 };
DWORD out_len = 0;
BOOL isFinal = FALSE;
DWORD readTotalSize = 0;
DWORD inputSize = GetFileSize(hInpFile, NULL);
while (bResult = ReadFile(hInpFile, chunk, chunk_size, &out_len, NULL)) {
if (0 == out_len) {
break;
}
printf("\nFile read.");
readTotalSize += out_len;
if (readTotalSize == inputSize) {
isFinal = TRUE;
printf("\nFinal chunk set.\n");
}
printf("\n Now calling decryption routine...");
if (!CryptDecrypt(hKey, NULL, isFinal, 0, chunk, &out_len)) {
printf("[-] CryptDecrypt failed\n");
break;
}
printf("CryptDecrypt succeeded.");
DWORD written = 0;
if (!WriteFile(hOutFile, chunk, out_len, &written, NULL)) {
printf("writing failed!\n");
break;
}
memset(chunk, 0, chunk_size);
}
CryptReleaseContext(hCryptProv, 0);
CryptDestroyKey(hKey);
CryptDestroyHash(hHash);
CloseHandle(hInpFile);
CloseHandle(hOutFile);
printf("Finished. Processed %#x bytes.\n", readTotalSize);
system("pause");
return 0;
}
Это просто заканчивается тем, что CryptDecrypt
не удалось. Я предполагаю, что ключ не был указан в правильном формате. Я не знаю, как использовать мой ключ AES-256 в шестнадцатеричном формате для расшифровки данных. В настоящее время ключ жестко запрограммирован в формате base64
в программе, но я предполагаю, что это неправильно.
Еще одна вещь, которую я сделал, это то, что я использовал инструмент CryptoTester , чтобы указать ключ AES, который у меня есть в шестнадцатеричном формате, и он действительно может успешно расшифровать файл. Кроме того, этот онлайн-инструмент дешифрования также может использовать ключ для дешифрования данных , как показано здесь . Итак, я знаю, что у меня есть правильный шестнадцатеричный ключ и все, и что файл можно расшифровать, но как мне переписать мою программу выше, чтобы правильно расшифровать файл?
Обратите внимание, что все ключи, используемые или показанные здесь, являются только примерами.
Как мне исправить эту программу, чтобы фактически успешно расшифровать данные, используя ключ AES-256 выше?