首页 > 解决方案 > 如何在最后一步使用 CryptDecrypt 解决 NTE_BAD_DATA

问题描述

我正在使用 WINAPI 使用 c++ 进行加密算法。我的加密工作完美无缺,我的解密也是如此,直到最后一个块用 final = TRUE 解密。我收到了 NTE_BAD_DATA 错误。

PS:我手动检查缓冲区并且解密工作正常,直到最后一次 CryptDecrypt。

如果有人有想法,请帮助我:)

这是我的代码:

PVOID test(PVOID buffer, DWORD* length, PCHAR key_str2,bool isdecrypt) {
CHAR default_key[] = "3igcZhRdWq96m3GUmTAiv9";
CHAR* key_str = default_key;

size_t len = lstrlenA(key_str);

DWORD dwStatus = 0;
BOOL bResult = FALSE;
wchar_t info[] = L"Microsoft Enhanced RSA and AES Cryptographic Provider";
HCRYPTPROV hProv;
if (!CryptAcquireContextW(&hProv, NULL, info, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
    dwStatus = GetLastError();
    CryptReleaseContext(hProv, 0);
    return 0;
}
HCRYPTHASH hHash;
if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {
    dwStatus = GetLastError();
    CryptReleaseContext(hProv, 0);
    return 0;
}

if (!CryptHashData(hHash, (BYTE*)key_str, len, 0)) {
    DWORD err = GetLastError();
    return 0;
}

HCRYPTKEY hKey;
if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey)) {
    dwStatus = GetLastError();
    CryptReleaseContext(hProv, 0);
    return 0;
}

const size_t chunk_size = CHUNK_SIZE;
BYTE chunk[chunk_size] = { 0 };
DWORD out_len = 0;

BOOL isFinal = FALSE;
DWORD readTotalSize = 0;

DWORD inputSize = *length;
PVOID newBuff = VirtualAlloc(0, inputSize, MEM_COMMIT, PAGE_READWRITE);
while (true)
{
    if (readTotalSize + chunk_size >= inputSize)
    {
        isFinal = TRUE;
        memcpy(chunk, PVOID((DWORD)buffer + readTotalSize), inputSize - readTotalSize);
        out_len = inputSize - readTotalSize;

    }
    else {
        memcpy(chunk, PVOID((DWORD)buffer + readTotalSize), chunk_size);
        out_len = chunk_size;
    }

    if (isdecrypt) {
        if (!CryptDecrypt(hKey, NULL, isFinal, 0, chunk, &out_len)) {
            int a = GetLastError();
            break;
        }
    }
    else {
        if (!CryptEncrypt(hKey, NULL, isFinal, 0, chunk, &out_len, chunk_size)) {
            break;
        }
    }
    if (readTotalSize + chunk_size >= inputSize) {
        memcpy(PVOID((DWORD)newBuff + readTotalSize), chunk, inputSize - readTotalSize);
        readTotalSize += inputSize - readTotalSize;
    }
    else {
        memcpy(PVOID((DWORD)newBuff + readTotalSize), chunk, chunk_size);
        readTotalSize += chunk_size;
    }

    if (isFinal)
        break;
    memset(chunk, 0, chunk_size);

}

CryptReleaseContext(hProv, 0);
CryptDestroyKey(hKey);
CryptDestroyHash(hHash);
return newBuff;

}

标签: c++winapicryptography

解决方案


您没有正确存储最终块的加密。

您传递到加密的数据量在out_len,加密的数据量被放回out_len。对于一个对整个块无关紧要的块密码,但是你的最后一个小于整个块的块被传递到加密可能会创建一个完整的加密数据块。

这意味着您的加密数据可能比最终块中的纯文本大一点,但是当您解密时遇到问题,您不会努力处理这个问题,因为您将一些加密数据丢弃在地板上.

使用out_len加密函数输入的值来存储您的数据(当您覆盖数据流时,您需要确保有空间)


推荐阅读