Как создать симметричный ключ для CryptDecrypt, используя необработанные значения шестнадцатеричного ключа в Windows CryptoAPI? - PullRequest
0 голосов
/ 06 июня 2019

После многих проб и ошибок я смог успешно зашифровать файл с помощью ключа AES-256 с помощью Windows CryptoAPI.

Программа шифрования выполняет следующие действия:

  • Исправляет длину блока до 128 бит (AES)
  • Создает ключ AES-256-CBC (CryptGenKey)
  • Шифрует файл с помощью этого ключа (CryptEncrypt)

Теперь, чтобы расшифровать файл, я хочу использовать ключ, который у меня есть в формате необработанных шестнадцатеричных значений.Например, у меня есть этот ключ:

76FD3DBDFA2AA07113A227D9E0311DC5BC7FA78A7E4FC3CE63919B9C49DC4F06

(обратите внимание, что этот ключ случайным образом генерируется в качестве примера , а не используется * *1024*), случайным образом *1023* генерируется онлайн *1024*.где угодно, чтобы что-нибудь обезопасить)

Все, что у меня есть, - это необработанное шестнадцатеричное значение ключа, как показано выше.Поэтому мне нужно иметь возможность передать его в функцию CryptDecrypt и расшифровать данные. Проблема:

CryptDecrypt ожидает, что ключ будет отправлен как тип данных HCRYPTKEY .Но все, что у меня есть, это ключ, хранящийся в этом формате:

wchar_t* key = argv[1]  //reading the key in hex format as an argument

Что я пробовал:

CryptDeriveKey , чтобы получить ключ вФормат HCRYPTKEY из базового значения.Однако CryptDeriveKey не примет мой ключ в формате шестнадцатеричных значений, в котором он у меня сейчас есть, поскольку ему, в свою очередь, нужен ключ в формате HCRYPTHASH.

На данный момент я не уверен, как я могу это сделатьиспользуйте необработанные шестнадцатеричные значения, которые у меня есть, в качестве ключа для CryptDecrypt для расшифровки данных.Я знаю, что это возможно, я просто не знаю, как туда добраться.

По причинам, в которые я не буду входить, я должен получить ключ из необработанных шестнадцатеричных значений, которые у меня есть(в отличие от любого другого ключевого формата, такого как байтовый массив) и передайте его в CryptDecrypt для расшифровки данных.

1 Ответ

1 голос
/ 07 июня 2019

Вы должны импортировать ключ с помощью функции CryptImportKey .

BOOL CryptImportKey(
  HCRYPTPROV hProv,
  const BYTE *pbData,
  DWORD      dwDataLen,
  HCRYPTKEY  hPubKey,
  DWORD      dwFlags,
  HCRYPTKEY  *phKey
);

hProv - дескриптор CSP, полученный с помощью функции CryptAcquireContext.
hPubKey - в вашем случае должно быть 0.
dwFlags - в вашем случае должно быть 0.
phKey - результирующий ключ, который ожидал CryptDecrypt.

А вот какая-то хитрая часть. pbData должна содержать структуру BLOBHEADER , за которой следует значение ключа.

typedef struct _PUBLICKEYSTRUC {
  BYTE   bType;
  BYTE   bVersion;
  WORD   reserved;
  ALG_ID aiKeyAlg;
} BLOBHEADER, PUBLICKEYSTRUC;

bType = PLAINTEXTKEYBLOB (0x08) - in your case  
bVersion = CUR_BLOB_VERSION (0x02) 
reserved = 0  
aiKeyAlg = algorithm id which you used in CryptGenKey

Пример кода:

BYTE key_value[] = { 0x76, 0xFD, 0x3D, 0xBD, 0xFA, 0x2A, 0xA0, 0x71, 0x13, 0xA2, 0x27, 0xD9, 0xE0, 0x31, 0x1D, 0xC5, 
    0xBC, 0x7F, 0xA7, 0x8A, 0x7E, 0x4F, 0xC3, 0xCE, 0x63, 0x91, 0x9B, 0x9C, 0x49, 0xDC, 0x4F, 0x06 };
BLOBHEADER bh;
bh.bType = PLAINTEXTKEYBLOB;
bh.bVersion = CUR_BLOB_VERSION;
bh.reserved = 0;
bh.aiKeyAlg = CALG_AES_256;

DWORD dwDataLen = sizeof(key_value) + sizeof(bh);
BYTE* pbData = (BYTE*)malloc(dwDataLen);
BYTE* ptr = pbData;
memcpy(ptr, (BYTE*)&bh, sizeof(bh));
ptr += sizeof(bh);
memcpy(ptr, key_value, sizeof(key_value));
if (!CryptImportKey(hProv, pbData, dwDataLen, 0, 0, &hKey)) {
    return GetLastError();
}
...