Rust实现CryptoJS AES ECB解密遇错误,请求技术支持
解决Rust中AES-ECB解密的UnpadError问题
问题背景
需要将JavaScript中的AES-ECB解密逻辑迁移到Rust,JavaScript示例代码运行正常,能正确完成加密解密流程:
const CryptoJS = require('crypto-js'); const key = "KeyIs16CharsLong"; const value = "Hello, Rust!"; const keyParsed = CryptoJS.enc.Utf8.parse(key); // 加密 const encrypted = CryptoJS.AES.encrypt(value, keyParsed, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }).toString(); console.log(key); // 'KeyIs16CharsLong' console.log(encrypted); // 'nFWwLNMi2toxug1hDb/HGg==' // 解密 const decrypted = CryptoJS.AES.decrypt(encrypted, keyParsed, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8); console.log("Decrypted:", decrypted); // Decrypted: Hello, Rust!
但在Rust中实现解密时,触发了UnpadError,原尝试代码如下:
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit}; use base64::Engine; use base64::engine::general_purpose; type Aes128EcbDec = ecb::Decryptor<aes::Aes128>; fn test_decryption() { let key = "KeyIs16CharsLong"; let plaintext = "nFWwLNMi2toxug1hDb/HGg=="; // Decode key and adjust to 16 bytes let mut key_vec = general_purpose::STANDARD.decode(key).expect("Invalid Base64 key"); key_vec.resize(16, 0); // Pad with zeros if the decoded key is too short let key: [u8; 16] = key_vec.try_into().expect("Key must be 16 bytes for AES-128"); // Convert ciphertext from hex to bytes let mut ciphertext = general_purpose::STANDARD.decode(plaintext).expect("Invalid Base64 ciphertext"); let pt = Aes128EcbDec::new(&key.into()) .decrypt_padded_mut::<Pkcs7>(&mut ciphertext) .unwrap(); // Convert decrypted plaintext to a string let decrypted_plaintext = String::from_utf8(pt.to_vec()).expect("Decryption produced invalid UTF-8"); println!("Decrypted plaintext: {}", decrypted_plaintext); }
运行时错误信息:
thread 'main' panicked at src/main.rs:30:10: called `Result::unwrap()` on an `Err` value: UnpadError
错误原因
核心问题是密钥处理逻辑完全错误:
- JavaScript中
CryptoJS.enc.Utf8.parse(key)是直接将密钥字符串转换为UTF-8字节数组作为AES密钥 - 原Rust代码错误地对密钥字符串执行了Base64解码,导致生成的密钥与JS侧加密使用的密钥完全不符,解密时无法还原正确明文,最终触发PKCS7解填充失败
修正后的代码
调整密钥处理逻辑,直接将字符串转为UTF-8字节数组即可:
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, KeyInit}; use base64::Engine; use base64::engine::general_purpose; type Aes128EcbDec = ecb::Decryptor<aes::Aes128>; fn test_decryption() { let key_str = "KeyIs16CharsLong"; let ciphertext_b64 = "nFWwLNMi2toxug1hDb/HGg=="; // 直接将密钥字符串转为UTF-8字节数组,无需Base64解码 let key_bytes = key_str.as_bytes(); // 确认密钥长度为16字节(AES-128要求),原字符串刚好16字符,UTF-8下每个字符占1字节 let key: [u8; 16] = key_bytes.try_into().expect("Key must be 16 bytes for AES-128"); // 解码Base64格式的密文 let mut ciphertext = general_purpose::STANDARD.decode(ciphertext_b64).expect("Invalid Base64 ciphertext"); // 解密并自动处理PKCS7解填充 let plaintext_bytes = Aes128EcbDec::new(&key.into()) .decrypt_padded_mut::<Pkcs7>(&mut ciphertext) .expect("Decryption or unpadding failed"); // 将明文字节转为UTF-8字符串 let decrypted_plaintext = String::from_utf8(plaintext_bytes.to_vec()).expect("Invalid UTF-8 in decrypted plaintext"); println!("Decrypted plaintext: {}", decrypted_plaintext); }
运行结果
修正后代码运行会输出:
Decrypted plaintext: Hello, Rust!
内容的提问来源于stack exchange,提问作者Captain Ildar
相关产品推荐
相关产品推荐

