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

使用Windows API开发的AES-256解密文件为何出现冗余文本?

文件解密后末尾出现冗余文本的问题分析与修复

核心问题

加密环节的错误

  • 未标记最后一块数据:调用CryptEncrypt时始终把final参数设为FALSE,导致所有数据块都被当作非最后一块处理,AES标准的PKCS#7填充不会自动添加。你手动把缓冲区扩展到块大小,但这不是规范的填充方式,解密时根本识别不出哪些是填充内容。
  • 手动计算缓冲区大小多余:CryptEncrypt本身会自动计算加密后的数据长度,手动算encryptedSize的操作完全没必要,还容易出错。

解密环节的错误

  • 没处理填充去除:CryptDecrypt的final参数也一直是FALSE,API不会自动去除PKCS#7填充,导致解密后的最后一块保留了加密时的填充字节,这就是你看到的末尾冗余文本。
  • 缓冲区处理逻辑有问题:直接把输入缓冲区复制到输出缓冲区,没考虑解密后数据长度的变化,配合未标记最后一块的问题,填充就彻底没法被去除了。

修复后的关键代码

加密函数修改

bool encryptFile(char* sourcePath, char* destPath, char* password) {
    // 省略文件打开、密钥生成等原有代码...

    BYTE buffer[BUFFER_SIZE];
    DWORD bytesRead, encryptedSize;
    BOOL success = TRUE;
    BOOL isFinal = FALSE;

    while ((bytesRead = fread(buffer, 1, BUFFER_SIZE, hSourceFile)) > 0) {
        // 判断是否为最后一块数据
        isFinal = (bytesRead < BUFFER_SIZE);

        // 先调用CryptEncrypt获取加密所需的缓冲区大小
        encryptedSize = bytesRead;
        if (!CryptEncrypt(hKey, NULL, isFinal, 0, NULL, &encryptedSize, 0)) {
            handleError(GetLastError());
            success = FALSE;
            break;
        }

        BYTE* encryptedBuffer = (BYTE*)malloc(encryptedSize);
        if (!encryptedBuffer) {
            success = FALSE;
            break;
        }
        memcpy(encryptedBuffer, buffer, bytesRead);

        // 执行加密操作
        if (!CryptEncrypt(hKey, NULL, isFinal, 0, encryptedBuffer, &bytesRead, encryptedSize)) {
            free(encryptedBuffer);
            handleError(GetLastError());
            success = FALSE;
            break;
        }

        fwrite(encryptedBuffer, 1, bytesRead, hDestFile);
        free(encryptedBuffer);
    }

    // 省略资源释放等原有代码...
}

解密函数修改

bool decryptFile(char* sourcePath, char* destPath, char* password) {
    // 省略文件打开、密钥生成等原有代码...

    BYTE bufferIn[BUFFER_SIZE];
    BYTE bufferOut[BUFFER_SIZE + AES_BLOCK_SIZE]; // 预留空间处理填充
    DWORD bytesRead, decryptedSize;
    BOOL success = TRUE;
    BOOL isFinal = FALSE;

    while ((bytesRead = fread(bufferIn, 1, BUFFER_SIZE, hSourceFile)) > 0) {
        // 读取后判断是否到达文件末尾
        isFinal = feof(hSourceFile);

        memcpy(bufferOut, bufferIn, bytesRead);
        decryptedSize = bytesRead;

        if (!CryptDecrypt(hKey, NULL, isFinal, 0, bufferOut, &decryptedSize)) {
            handleError(GetLastError());
            success = FALSE;
            break;
        }

        fwrite(bufferOut, 1, decryptedSize, hDestFile);
    }

    // 省略资源释放等原有代码...
}

额外注意事项

  • 判断最后一块时,必须在fread之后调用feof,因为fread返回0才会触发EOF标记。
  • 解密时输出缓冲区要预留比输入大的空间(比如加AES_BLOCK_SIZE),防止解密时缓冲区不足导致失败。
  • 当前密钥派生没有加盐,相同密码会生成相同密钥,建议添加随机盐值写入加密文件开头,提高安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 01:46:02