使用Rust OpenSSL解密AES失败,JS CryptoJS可正常解密求助
问题分析与解决
错误根源
你的Rust代码存在两个核心问题:
- 错误拆分密码字符串:CryptoJS是将完整的
"24408752.37717366"作为密码来推导密钥和IV,而非将其拆分为盐(SALT)和密钥(KEY)两部分。 - 未处理CryptoJS密文格式:CryptoJS生成的密文通常是Base64编码,且带有
Salted__前缀(前8字节),其中包含密钥推导所需的盐值,你的代码未正确提取该盐。
修正后的Rust代码
use openssl::symm::{decrypt, Cipher}; use openssl::pkcs5::bytes_to_key; use openssl::hash::MessageDigest; use base64::engine::general_purpose::STANDARD as BASE64_STD; use base64::Engine as _; fn decrypt_cryptojs_aes(encrypted_base64: &str, password: &str) -> Result<String, Box<dyn std::error::Error>> { // 1. 解码Base64密文(CryptoJS默认输出Base64格式) let encrypted_bytes = BASE64_STD.decode(encrypted_base64)?; // 2. 提取盐和实际密文:CryptoJS密文格式为 Salted__ + 8字节盐 + 密文内容 let (salt, ciphertext) = if encrypted_bytes.starts_with(b"Salted__") { (&encrypted_bytes[8..16], &encrypted_bytes[16..]) } else { // 无Salted__前缀时使用空盐(CryptoJS默认加密会加盐,此情况少见) (&[], &encrypted_bytes) }; // 3. 对齐CryptoJS的密钥推导逻辑:EVP_BytesToKey + MD5 + 1次迭代 let cipher = Cipher::aes_256_cbc(); let key_iv = bytes_to_key( cipher, MessageDigest::md5(), password.as_bytes(), Some(salt), 1 )?; // 4. 执行解密 let decrypted_bytes = decrypt( cipher, &key_iv.key, key_iv.iv.as_deref(), ciphertext )?; // 转换为UTF-8字符串返回 Ok(String::from_utf8(decrypted_bytes)?) } // 使用示例 fn main() -> Result<(), Box<dyn std::error::Error>> { let encrypted_text = "你的加密字符串"; let password = "24408752.37717366"; let decrypted = decrypt_cryptojs_aes(encrypted_text, password)?; println!("解密结果: {}", decrypted); Ok(()) }
关键注意事项
- Base64解码:CryptoJS的
AES.decrypt会自动处理Base64密文,Rust代码需手动完成这一步。 - 盐提取逻辑:必须从密文中提取CryptoJS自动添加的盐值,才能保证密钥推导结果和JS端一致。
- 参数对齐:密钥推导必须使用MD5哈希、1次迭代、完整密码字符串,完全匹配CryptoJS的默认行为。
内容的提问来源于stack exchange,提问作者frederik
相关产品推荐
相关产品推荐

