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

如何在Windows下用C语言实现无外部库的AES-256 GCM解密?

Windows下无外部依赖实现AES-256 GCM解密(C语言)

核心方案:使用系统预装的BCrypt API

Windows原生的bcrypt.h属于系统预装组件,无需额外安装第三方库,完全满足你的需求。

解决你遇到的问题

1. 初始错误(STATUS_INVALID_PARAMETER)

你最初碰到的0xC000000D错误,根源通常是两个点:

  • 未正确分离认证标签:GCM模式下标签默认16字节,需从加密输出的末尾单独提取,不能和密文混在一起传入解密函数
  • 结构体初始化错误:BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO必须用BCRYPT_INIT_AUTH_MODE_INFO宏初始化,不能直接用memset,否则会遗漏关键的cbSize字段设置

2. 输出长度过长、多余字节问题

这个问题是因为未正确获取并设置明文的实际有效长度。以下是修正后的完整示例代码,可解决上述所有问题:

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

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

#define AES_256_KEY_SIZE 32
#define GCM_IV_SIZE 12
#define GCM_TAG_SIZE 16

NTSTATUS AES256GCM_Decrypt(
    const BYTE* pKey,
    const BYTE* pIV,
    const BYTE* pCiphertext,
    DWORD cbCiphertext,
    const BYTE* pTag,
    const BYTE* pAdditionalData,
    DWORD cbAdditionalData,
    BYTE* pPlaintext,
    DWORD* pcbPlaintext
) {
    NTSTATUS status;
    BCRYPT_ALG_HANDLE hAlg = NULL;
    BCRYPT_KEY_HANDLE hKey = NULL;
    DWORD cbResult = 0;

    // 打开AES算法句柄
    status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, NULL, 0);
    if (!BCRYPT_SUCCESS(status)) goto Cleanup;

    // 设置算法为GCM模式
    status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE, (BYTE*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0);
    if (!BCRYPT_SUCCESS(status)) goto Cleanup;

    // 导入256位AES密钥
    status = BCryptGenerateSymmetricKey(hAlg, &hKey, NULL, 0, (BYTE*)pKey, AES_256_KEY_SIZE, 0);
    if (!BCRYPT_SUCCESS(status)) goto Cleanup;

    // 初始化认证模式结构体(必须用官方宏)
    BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo;
    BCRYPT_INIT_AUTH_MODE_INFO(authInfo);
    authInfo.pbNonce = (BYTE*)pIV;
    authInfo.cbNonce = GCM_IV_SIZE;
    authInfo.pbTag = (BYTE*)pTag;
    authInfo.cbTag = GCM_TAG_SIZE;
    authInfo.pbAuthData = (BYTE*)pAdditionalData;
    authInfo.cbAuthData = cbAdditionalData;

    // 先调用一次获取所需的明文缓冲区大小
    status = BCryptDecrypt(hKey, (BYTE*)pCiphertext, cbCiphertext, &authInfo, NULL, 0, NULL, 0, pcbPlaintext, BCRYPT_BLOCK_PADDING);
    if (!BCRYPT_SUCCESS(status)) goto Cleanup;

    // 执行实际解密操作
    status = BCryptDecrypt(hKey, (BYTE*)pCiphertext, cbCiphertext, &authInfo, NULL, 0, pPlaintext, *pcbPlaintext, &cbResult, BCRYPT_BLOCK_PADDING);
    if (!BCRYPT_SUCCESS(status)) goto Cleanup;

    // 更新为实际明文长度,避免多余字节
    *pcbPlaintext = cbResult;

Cleanup:
    if (hKey) BCryptDestroyKey(hKey);
    if (hAlg) BCryptCloseAlgorithmProvider(hAlg, 0);
    return status;
}

int main() {
    // 示例数据(对应Python AES-GCM加密后的解码结果)
    BYTE key[AES_256_KEY_SIZE] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
                                  0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F};
    BYTE iv[GCM_IV_SIZE] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B};
    // 密文(已分离末尾16字节的标签)
    BYTE ciphertext[] = {0x69,0xC4,0xE0,0xD8,0x6A,0x7B,0x04,0x30,0xD8,0xCD,0xB7,0x80,0x70,0xB4,0xC5,0x5A};
    DWORD cbCiphertext = sizeof(ciphertext);
    BYTE tag[GCM_TAG_SIZE] = {0x1A,0x80,0x7D,0x27,0x2B,0x45,0xBC,0xBF,0xE0,0x79,0xAD,0x27,0xDA,0xAF,0x5F,0x77};
    // 附加数据(加密时如果用了,解密必须传完全相同的内容;无则设为NULL,长度0)
    BYTE additionalData[] = {0x41,0x54,0x54,0x41};
    DWORD cbAdditionalData = sizeof(additionalData);

    BYTE plaintext[1024] = {0};
    DWORD cbPlaintext = sizeof(plaintext);

    NTSTATUS status = AES256GCM_Decrypt(key, iv, ciphertext, cbCiphertext, tag, additionalData, cbAdditionalData, plaintext, &cbPlaintext);
    if (BCRYPT_SUCCESS(status)) {
        printf("解密成功,明文:%.*s\n", cbPlaintext, plaintext);
    } else {
        printf("解密失败,错误码:0x%X\n", status);
    }

    return 0;
}

关键注意事项

  • 标签分离:Python的AES-GCM加密输出一般是密文+标签的拼接形式,解密前必须把最后16字节的标签单独提取出来
  • 结构体初始化:BCRYPT_INIT_AUTH_MODE_INFO宏会自动设置结构体的版本和大小字段,这是避免参数错误的核心
  • 输出长度控制:先调用BCryptDecrypt获取准确的明文长度,再分配对应缓冲区,就能解决多余字节问题
  • 附加数据一致性:加密时使用的附加数据(AD),解密时必须完全一致,否则认证会失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 02:20:30