gpt4 book ai didi

c++ - CNG 中的 AES-CBC 加密输出与在线工具不匹配

转载 作者:行者123 更新时间:2023-11-27 23:55:22 27 4
gpt4 key购买 nike

我是 CNG 新手。我正在玩 msdn 站点的基本程序。我修改了输入纯字符串并使用提供 aes cbc 加密输出的其他网站测试了输出。不幸的是只有上半场匹配,下半场不匹配。如果有人能指出错误所在,那就太好了,

来自 msdn 的原始代码是 here .

这是我的代码生成的输出(如下)。请注意,除了修改输入纯字符串外,我的代码没有任何区别。 enter image description here

这是在线网站的输出(http://aes.online-domain-tools.com/anothersite) enter image description here

上半场结束于“B0 C4 29 18”..之后,下半场不匹配。

这是代码片段

#include <windows.h>
#include <stdio.h>
#include <bcrypt.h>

#pragma comment(lib, "bcrypt.lib")

#ifndef STATUS_UNSUCCESSFUL
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
#endif // !STATUS_UNSUCCESSFUL

#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#endif

void
print_inhex(char *buf, int len) {
for (int i = 0; i < len; i++)
printf(" %02x", buf[i]);
printf("\n");
}

const BYTE rgbPlaintext[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};

static const BYTE rgbIV[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};

static const BYTE rgbAES128Key[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};


void
CNG_aes_cbc()
{

BCRYPT_ALG_HANDLE hAesAlg = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
DWORD cbCipherText = 0,
cbPlainText = 0,
cbData = 0,
cbKeyObject = 0,
cbBlockLen = 0,
cbBlob = 0;
PBYTE pbCipherText = NULL,
pbPlainText = NULL,
pbKeyObject = NULL,
pbIV = NULL,
pbBlob = NULL;

// Open an algorithm handle.
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hAesAlg, BCRYPT_AES_ALGORITHM, NULL, 0))) {
wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
goto Cleanup;
}

// Calculate the size of the buffer to hold the KeyObject.
if (!NT_SUCCESS(status = BCryptGetProperty(hAesAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbKeyObject, sizeof(DWORD), &cbData, 0))) {
wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
goto Cleanup;
}

// Allocate the key object on the heap.
pbKeyObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbKeyObject);
if (NULL == pbKeyObject) {
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}

// Calculate the block length for the IV.
if (!NT_SUCCESS(status = BCryptGetProperty(hAesAlg, BCRYPT_BLOCK_LENGTH, (PBYTE)&cbBlockLen, sizeof(DWORD), &cbData, 0))) {
wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
goto Cleanup;
}

// Determine whether the cbBlockLen is not longer than the IV length.
if (cbBlockLen > sizeof(rgbIV)) {
wprintf(L"**** block length is longer than the provided IV length\n");
goto Cleanup;
}

// Allocate a buffer for the IV. The buffer is consumed during the
// encrypt/decrypt process.
pbIV = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbBlockLen);
if (NULL == pbIV) {
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}

memcpy(pbIV, rgbIV, cbBlockLen);

if (!NT_SUCCESS(status = BCryptSetProperty(hAesAlg, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0))) {
wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status);
goto Cleanup;
}

// Generate the key from supplied input key bytes.
if (!NT_SUCCESS(status = BCryptGenerateSymmetricKey(hAesAlg, &hKey, pbKeyObject, cbKeyObject, (PBYTE)rgbAES128Key, sizeof(rgbAES128Key), 0))) {
wprintf(L"**** Error 0x%x returned by BCryptGenerateSymmetricKey\n", status);
goto Cleanup;
}


// Save another copy of the key for later.
if (!NT_SUCCESS(status = BCryptExportKey(hKey, NULL, BCRYPT_KEY_DATA_BLOB, NULL, 0, &cbBlob, 0))) {
wprintf(L"**** Error 0x%x returned by BCryptExportKey\n", status);
goto Cleanup;
}


// Allocate the buffer to hold the BLOB.
PUCHAR pbBlob_1 = (PUCHAR)malloc(sizeof(PUCHAR) * cbBlob);
//pbBlob = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbBlob);
if (NULL == pbBlob_1) {
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}

if (!NT_SUCCESS(status = BCryptExportKey(hKey, NULL, BCRYPT_KEY_DATA_BLOB, pbBlob_1, cbBlob, &cbBlob, 0))) {
wprintf(L"**** Error 0x%x returned by BCryptExportKey\n", status);
goto Cleanup;
}

PUCHAR blob = pbBlob_1 + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER);
int len = cbBlob - sizeof(BCRYPT_KEY_DATA_BLOB_HEADER);
printf("key:");
print_inhex(blob, len);

cbPlainText = sizeof(rgbPlaintext);
pbPlainText = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbPlainText);
if (NULL == pbPlainText) {
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}

/*memcpy(pbPlainText, rgbPlaintext, sizeof(rgbPlaintext));*/
char *test_msg = "This is my test msg";
cbPlainText = strlen(test_msg) + 1;
memcpy(pbPlainText, test_msg, cbPlainText);

printf("plain text:");
print_inhex(test_msg, strlen(test_msg));

// Get the output buffer size.
if (!NT_SUCCESS(status = BCryptEncrypt(hKey, pbPlainText, cbPlainText, NULL, pbIV, cbBlockLen, NULL, 0, &cbCipherText, BCRYPT_BLOCK_PADDING))) {
wprintf(L"**** Error 0x%x returned by BCryptEncrypt\n", status);
goto Cleanup;
}

pbCipherText = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbCipherText);
if (NULL == pbCipherText) {
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}

// Use the key to encrypt the plaintext buffer.
// For block sized messages, block padding will add an extra block.
if (!NT_SUCCESS(status = BCryptEncrypt(hKey, pbPlainText, cbPlainText, NULL, pbIV,
cbBlockLen, pbCipherText, cbCipherText, &cbData, BCRYPT_BLOCK_PADDING))){
wprintf(L"**** Error 0x%x returned by BCryptEncrypt\n", status);
goto Cleanup;
}

printf("cipher text:");
for (int i = 0; i < cbCipherText; i++)
printf(" %02x", pbCipherText[i]);

wprintf(L"\nSuccess!\n");

Cleanup:
if (hAesAlg)
BCryptCloseAlgorithmProvider(hAesAlg, 0);

if (hKey)
BCryptDestroyKey(hKey);

if (pbCipherText)
HeapFree(GetProcessHeap(), 0, pbCipherText);

if (pbKeyObject)
HeapFree(GetProcessHeap(), 0, pbKeyObject);

if (pbIV)
HeapFree(GetProcessHeap(), 0, pbIV);
}

最佳答案

您与 cbPlainText 的值不一致。

旁白:

  • 您还有一些非常可怕的复制/重新分配代码,您在其中将字符串写入缓冲区,但不能保证与字符串一样大)。
  • 您还定义了 NT_SUCCESS,无论是否失败,它都会返回。 0 为成功,!0 为失败。

你用十六进制打印了 strlen 个 tst_msg。但是你设置了 cbPlainText = strlen(tst_msg) + 1。如果你将它设置为 strlen(tst_msg) 那么你会得到@zaph 的答案(46CC2228E81B2A05E8E8EBF2B0C42918EC496128D7C45BD0B19BB2D6452A3936)。

您不匹配该网站,因为您使用了带有 PKCS#7 填充的 CNG,而该网站使用了零填充。您可以通过获取输出密文并将其作为明文然后点击解密来识别网站中使用的填充。然后它说您的输入是 54686973206973206d792074657374206d736700000000000000000000000000。或者,如果您在网站输入中添加 00 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C,您将获得原始答案。或者添加 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D,你会得到@zaph 的答案。

那么,要做的事情:

  • 不要重新评估要打印的内容的长度,创建一个变量 (cbPlainText) 并坚持使用它。
  • AES 是一种分组密码算法。所有 block 密码都需要完整的 block ,必须填充有缺陷的最后一个 block (并且在可移动填充方案下,完整的最后一个 block 需要另一个 block )。在继续之前了解这意味着什么。 https://en.wikipedia.org/wiki/Padding_(cryptography)#Symmetric_cryptography
  • 当加密出现问题时,查看解密后的输出。
    • “无填充”的解密输出经常会泄露信息。
  • 学习 C 语言以及内存的工作原理。或者切换到 C# 并且学习曲线不那么陡峭。

关于c++ - CNG 中的 AES-CBC 加密输出与在线工具不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43011261/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com