You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BCryptDecrypt(CNG)API无法正确解密原CryptDecrypt加密数据

问题分析与修复方案

你的代码存在多个关键逻辑错误,导致解密结果乱码,以下是具体问题和修复方法:

1. IV 使用错误

解密必须使用加密时的同一初始向量(IV),但你当前代码调用BCryptGenRandom生成了新的IV,这会直接导致解密失败。通常加密流程中会将IV附加在密文头部,解密时需要先从密文中提取原始IV,而不是重新生成。

2. 链模式设置时机错误

BCryptSetProperty设置BCRYPT_CHAINING_MODE必须在创建密钥(BCryptGenerateSymmetricKey或BCryptImportKey)之前执行,因为密钥对象会绑定算法的链模式参数。你当前是先创建密钥再设置链模式,导致CBC模式并未实际生效。

3. 密钥处理逻辑混乱

代码中同时调用了BCryptGenerateSymmetricKey和BCryptImportKey,且BCryptImportKey的参数pbKeyObject、cbKeyObject均为0,这会导致密钥状态异常。如果你的原始密钥是字节数组,直接使用BCryptGenerateSymmetricKey即可,无需额外调用BCryptImportKey。

4. 未明确指定填充模式

CryptDecrypt默认使用PKCS#7填充,而BCryptDecrypt需要显式指定填充模式(除非加密时未使用填充)。你需要在算法上下文设置填充属性,或在BCryptDecrypt的最后一个参数传入BCRYPT_PADDING_PKCS7。

5. 其他代码问题

  • 未定义变量_Data、Result,属于逻辑漏洞
  • wprinft拼写错误,应为wprintf
  • 未清理hKey、m_Context、pbIV等资源,会导致内存泄漏

修正后的示例代码

#include <windows.h>
#include <bcrypt.h>
#include <vector>
#pragma comment(lib, "bcrypt.lib")

bool decrypt(PBYTE pbCipherText, DWORD cbCipherText, const BYTE* KeyData, DWORD KeySize, std::vector<BYTE>& outPlainText)
{
    BCRYPT_ALG_HANDLE hAlg = NULL;
    BCRYPT_KEY_HANDLE hKey = NULL;
    PBYTE pbIV = nullptr;
    DWORD cbBlockLen = 0;
    DWORD cbData = 0;
    NTSTATUS status = 0;
    bool ret = false;

    // 1. 打开算法提供者,先设置链模式和填充模式
    if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, NULL, 0)))
    {
        wprintf(L"BCryptOpenAlgorithmProvider failed: 0x%x\n", status);
        goto Cleanup;
    }

    // 设置CBC链模式(必须在创建密钥前)
    if (!NT_SUCCESS(status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0)))
    {
        wprintf(L"BCryptSetProperty(chain mode) failed: 0x%x\n", status);
        goto Cleanup;
    }

    // 设置PKCS#7填充模式(匹配CryptDecrypt默认行为)
    if (!NT_SUCCESS(status = BCryptSetProperty(hAlg, BCRYPT_PADDING_SCHEMES, (PBYTE)BCRYPT_PADDING_PKCS7, sizeof(BCRYPT_PADDING_PKCS7), 0)))
    {
        wprintf(L"BCryptSetProperty(padding) failed: 0x%x\n", status);
        goto Cleanup;
    }

    // 获取块长度,用于IV处理
    if (!NT_SUCCESS(status = BCryptGetProperty(hAlg, BCRYPT_BLOCK_LENGTH, (PBYTE)&cbBlockLen, sizeof(DWORD), &cbData, 0)))
    {
        wprintf(L"BCryptGetProperty(block length) failed: 0x%x\n", status);
        goto Cleanup;
    }

    // 检查密文长度:至少包含IV + 加密数据
    if (cbCipherText < cbBlockLen)
    {
        wprintf(L"Invalid ciphertext length\n");
        goto Cleanup;
    }

    // 提取加密时使用的IV(假设IV存储在密文头部)
    pbIV = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbBlockLen);
    if (!pbIV)
    {
        wprintf(L"HeapAlloc for IV failed\n");
        goto Cleanup;
    }
    memcpy(pbIV, pbCipherText, cbBlockLen);
    // 密文主体是IV之后的部分
    PBYTE pbActualCipherText = pbCipherText + cbBlockLen;
    DWORD cbActualCipherText = cbCipherText - cbBlockLen;

    // 2. 生成对称密钥
    if (!NT_SUCCESS(status = BCryptGenerateSymmetricKey(hAlg, &hKey, nullptr, 0, (PBYTE)KeyData, KeySize, 0)))
    {
        wprintf(L"BCryptGenerateSymmetricKey failed: 0x%x\n", status);
        goto Cleanup;
    }

    // 3. 获取明文所需长度
    DWORD cbPlainText = 0;
    if (!NT_SUCCESS(status = BCryptDecrypt(hKey, pbActualCipherText, cbActualCipherText, NULL, pbIV, cbBlockLen, NULL, 0, &cbPlainText, BCRYPT_PADDING_PKCS7)))
    {
        wprintf(L"BCryptDecrypt(get length) failed: 0x%x\n", status);
        goto Cleanup;
    }

    // 分配明文内存
    outPlainText.resize(cbPlainText);
    if (!NT_SUCCESS(status = BCryptDecrypt(hKey, pbActualCipherText, cbActualCipherText, NULL, pbIV, cbBlockLen, outPlainText.data(), cbPlainText, &cbPlainText, BCRYPT_PADDING_PKCS7)))
    {
        wprintf(L"BCryptDecrypt failed: 0x%x\n", status);
        goto Cleanup;
    }

    ret = true;

Cleanup:
    // 清理资源
    if (hKey) BCryptDestroyKey(hKey);
    if (hAlg) BCryptCloseAlgorithmProvider(hAlg, 0);
    if (pbIV) HeapFree(GetProcessHeap(), 0, pbIV);
    return ret;
}

关键说明

  • 确保加密时将IV附加在密文头部,解密时先提取该IV
  • 链模式和填充模式必须与CryptDecrypt的加密参数完全匹配
  • 所有资源必须在退出前清理,避免内存泄漏

内容的提问来源于stack exchange,提问作者RituV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 12:43:10