Как расшифровать зашифрованный текст AES с помощью NCryptDecrypt в Windows

Я пытаюсь использовать Ncrypt.lib для шифрования простого текста с AES, а затем расшифровать его.

Я использую Ncrypt.lib, потому что я хочу использовать постоянный симметричный ключ.

Моя проблема в том, что расшифровка работает частично. Действительно, мои первые 16 байтов не расшифрованы правильно.

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <ncrypt.h>
#include <bcrypt.h>

void PrintBytes(
IN BYTE     *pbPrintData,
IN DWORD    cbDataLen) {
DWORD dwCount = 0;

for (dwCount = 0; dwCount < cbDataLen; dwCount++) {
printf("0x%02x, ", pbPrintData[dwCount]);

if (0 == (dwCount + 1) % 10) putchar('\n');
}
}

int main() {

BYTE plaintext[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
static const int plainTextLen = 48;

printf("PlainText:\n");
PrintBytes(plaintext, plainTextLen);
printf("\n");

LPCWSTR keyName = L"NCryptTest";
SECURITY_STATUS status;
NCRYPT_PROV_HANDLE hProvider;
NCRYPT_KEY_HANDLE hKey;

// Open storage provider
status = NCryptOpenStorageProvider(&hProvider, NULL, 0);

// Get stored key
status = NCryptOpenKey(hProvider, &hKey, keyName, 0, 0);
if (status == NTE_BAD_KEYSET) {
// Create key if it doesn't exist
status = NCryptCreatePersistedKey(hProvider, &hKey, BCRYPT_AES_ALGORITHM, keyName, 0, 0);
status = NCryptFinalizeKey(hKey, 0);
}

// Set the chaining mode to cipher feedback
LPCWSTR chainMode = BCRYPT_CHAIN_MODE_CFB;
status = NCryptSetProperty(hKey, NCRYPT_CHAINING_MODE_PROPERTY,
(PBYTE)chainMode, wcslen(chainMode) * 2 + 2, 0);

// Random iv but here, it's fixed
//char* iv = "0123456789abcdef";
//status = NCryptSetProperty(hKey, BCRYPT_INITIALIZATION_VECTOR,
//(PBYTE)iv, 16, 0);

// Get size of the cipher text
DWORD cbCipherText = 0;
status = NCryptEncrypt(hKey, plaintext, plainTextLen, NULL, NULL, 0,
&cbCipherText, 0);
PBYTE pbCipherText = NULL;
pbCipherText = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbCipherText);
if (pbCipherText == NULL) {
printf("Error! memory allocation failed\n");
}

// Encrypt
DWORD outlen = -1;
status = NCryptEncrypt(hKey, plaintext, plainTextLen, NULL, pbCipherText,
cbCipherText, &outlen, 0);
printf("CipherText:\n");
PrintBytes(pbCipherText, cbCipherText);
printf("\n");

// Get size of the plain text
DWORD cbPlainText = 0;
status = NCryptDecrypt(hKey, pbCipherText, cbCipherText, NULL, NULL, 0,
&cbPlainText, 0);
PBYTE pbPlainText = NULL;
pbPlainText = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbPlainText);
if (pbPlainText == NULL) {
printf("Error! memory allocation failed\n");
}

// Decrypt
outlen = -1;
status = NCryptDecrypt(hKey, pbCipherText, cbCipherText, NULL,
pbPlainText, cbPlainText, &outlen, 0);
printf("PlainText:\n");
PrintBytes(pbPlainText, cbPlainText);
printf("\n");

// Cleanup
NCryptFreeObject(hKey);
NCryptFreeObject(hProvider);

getchar();
return 0;
}

И результат:

PlainText:
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,

CipherText:
0xc5, 0xdc, 0x7e, 0xde, 0x83, 0x35, 0xbc, 0x34, 0x27, 0x4b,
0xf9, 0xde, 0x40, 0x36, 0xeb, 0x6d, 0xaf, 0x51, 0x8c, 0x48,
0x69, 0xa0, 0x16, 0xfb, 0x6d, 0x80, 0x44, 0xea, 0x5c, 0x74,
0x27, 0x38, 0xf1, 0x20, 0xa3, 0x87, 0x65, 0xc3, 0xcf, 0x62,
0x94, 0x84, 0xc9, 0xcd, 0x55, 0x4c, 0x7b, 0x48,

PlainText:
0x1d, 0x52, 0x88, 0x1b, 0x0c, 0x01, 0x13, 0xed, 0xe0, 0x39,
0x1e, 0x96, 0x67, 0x39, 0x72, 0x38, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,

Я подозреваю, что проблема вектора инициализации, но я не знаю, как ее использовать, просто с помощью BCRYPT_INITIALIZATION_VECTOR? или я должен поместить случайный iv перед простым текстом?

Спасибо за вашу помощь.

0

Решение

Ответ в комментарии:

это происходит потому, что каждый успешный вызов NCryptEncrypt или NCryptDecrypt изменяет состояние hKey. поэтому вы не можете использовать тот же ключ. после шифрования — вам нужно снова получить ключ для расшифровки — RbMm

Спасибо @RbMm!

0

Другие решения

Других решений пока нет …