WinAPI C++ AES-256-CBC加密后OpenSSL解密报块长度错误问题
WinAPI AES-256-CBC加密后OpenSSL解密失败问题修复
你代码里存在4个直接导致解密失败的错误,和字节序、加密算法兼容性无关:
- 无意义的全密文反转操作
WinAPI AES加密输出的密文字节流本身就是标准网络序(大端),和OpenSSL的输入要求完全一致,你调用ReverseStream把整个密文完全倒序,直接破坏了密文块顺序和块对齐规则,是触发wrong final block length错误的核心原因。 - 加密接口调用逻辑错误
你两次调用CryptEncrypt时长度参数使用混乱:第一次调用查询所需缓冲区大小时拿到的是预估最大长度,第二次实际加密完成后返回的dwBufSize2才是真实密文长度,你写文件时用了预估长度dwBufSize,会把缓冲区里未初始化的垃圾值一并写入文件,导致密文长度和内容异常。同时你用StrCpyA拷贝明文到加密缓冲区,会额外在明文末尾写入1字节的字符串结束符\0,导致实际加密的明文比预期多1字节,填充逻辑异常。 - 文件写入逻辑笔误
你判断文件句柄有效性时用的变量是ResList,实际调用WriteFile时传入的句柄是res,两个变量不统一的情况下,要么写文件完全失败,要么写入到错误的句柄,生成的encrypted.txt内容本身就是损坏的。 - 密钥Blob拷贝存在越界风险
你用StrCpyA拷贝密钥到AESBlob.szBytes时,会自动在32字节密钥后追加1字节结束符,容易造成结构体内存越界,覆盖相邻字段值。
修复步骤
- 直接删除
ReverseStream相关逻辑,加密完成后直接使用pBuf中存储的原始密文写文件即可,不需要做任何字节序转换。 - 替换所有
StrCpyA的明文、密钥、IV拷贝逻辑为memcpy,严格按照实际长度拷贝,避免自动追加结束符:
// 替换密钥拷贝 memcpy(AESBlob.szBytes, szKey, DEFAULT_AES_KEY_SIZE); // 替换明文拷贝 memcpy(pBuf, szPlainText, dwPlainSize);
- 修正文件写入逻辑,统一文件句柄变量,写文件时使用第二次加密返回的真实密文长度:
// 统一句柄变量,示例用hFile代替你混写的res/ResList if (hFile != INVALID_HANDLE_VALUE) { WriteFile( hFile, pBuf, dwBufSize2, // 用真实密文长度,不要用预估长度 &bytesWritten, NULL); CloseHandle(hFile); }
- 修正OpenSSL解密命令,直接传入原始密钥和IV时不需要走密钥派生,加
-pbkdf2参数即可消除版本警告:
openssl aes-256-cbc -d -nosalt -pbkdf2 \ -K "3030313132323333343435353636373738383939303031313232333334343535" \ -iv "34343535363637373838393930303131" \ -in encrypted.txt -out secrets.txt
注:WinAPI的AES实现默认使用PKCS7填充,和OpenSSL默认填充规则完全一致,不需要额外加
-nopad参数。
修复后本地WinAPI解密和Linux端OpenSSL解密都可以正常得到原始明文。
内容的提问来源于stack exchange,提问作者rmroot
相关产品推荐
相关产品推荐

