Rust AES-128 ECB长文本解密报InvalidPadding错误排查
问题原因
解密报InvalidPadding的核心原因是输出缓冲区处理逻辑错误,具体有两点:
- 加密函数返回的密文携带大量冗余零字节:加密时初始化的结果缓冲区长度为明文长度的4倍,但加密完成后没有根据实际写入的有效密文长度截断缓冲区,直接把整个4倍长度的Vec返回。短文本场景下冗余零字节长度短,PKCS填充校验可能碰巧通过;长文本场景下,尾部冗余的零字节会被当作有效密文参与解密运算,直接导致填充校验失败。这也解释了为什么同密文用Java可正常解密——你传给Java的密文是截取了有效长度的,没有携带尾部冗余零字节。
- 解密函数未截断输出、错误处理逻辑有缺陷:解密时初始化的结果缓冲区长度等于输入密文长度,解密完成后没有按实际写入的明文长度截断;且原有逻辑无论解密成功还是失败,都会直接返回结果Vec,哪怕解密失败也会返回带无效数据的缓冲区。
修复方案
两个函数都需要在加解密完成后,通过write_buffer.position()获取实际写入的字节数,对结果Vec做截断处理,只保留有效数据,同时修正解密逻辑的错误处理。
修复后的加密函数:
fn encrypt(key: &[u8], text: &[u8]) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> { let mut encryptor = crypto::aes::ecb_encryptor( KeySize128, key, PkcsPadding, ); let mut read_buffer = RefReadBuffer::new(text); // AES块长16字节,PKCS填充最多追加16字节,缓冲区给明文长度+16足够,无需分配4倍大小 let mut result = vec![0; text.len() + 16]; let mut write_buffer = RefWriteBuffer::new(&mut result); encryptor.encrypt(&mut read_buffer, &mut write_buffer, true).unwrap(); // 截断到实际写入长度,丢弃尾部未使用的零字节 let actual_len = write_buffer.position(); result.truncate(actual_len); Ok(result) }
修复后的解密函数:
fn decrypt(key: &[u8], text: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> { let mut decryptor = crypto::aes::ecb_decryptor( KeySize128, key, PkcsPadding, ); let mut read_buffer = RefReadBuffer::new(text); let mut result = vec![0; text.len()]; let mut write_buffer = RefWriteBuffer::new(&mut result); // 解密失败直接返回错误,不要吞错返回无效数据 decryptor.decrypt(&mut read_buffer, &mut write_buffer, true)?; // 截断到实际写入的明文长度 let actual_len = write_buffer.position(); result.truncate(actual_len); Ok(result) }
注意:你使用的
rust-crypto库已停止维护多年,存在已知安全漏洞,生产环境建议替换为RustCrypto组织维护的aes、ecb等活跃维护的密码学库。
内容的提问来源于stack exchange,提问作者zebei li
相关产品推荐
相关产品推荐

