使用openssl_decrypt解密Ionic AES加密数据无输出,如何解决?
PHP解密CryptoJS AES加密数据失败的解决方案
你的问题核心在于CryptoJS与OpenSSL的密钥处理逻辑、密文格式不匹配:
- 当CryptoJS使用字符串作为密钥时,会自动通过PBKDF2算法派生实际AES密钥,同时生成随机salt,并输出包含salt的OpenSSL兼容格式密文(开头为
U2FsdGVkX1...)。 - 你的PHP代码直接使用原始字符串密钥和IV解密,未处理salt提取与密钥派生逻辑,导致解密失败。
修正后的PHP解密代码
<?php $iv = "048eb25d7a45ff00"; $key = "feda4f2f67e7aa96"; $encrypted = "U2FsdGVkX1+kBV6Q5BQrjuOdi4WLiu4+QAnDIkzJYv5ATTkiiPVX8VcDUpMqSeIwCfyTNQOosp/9nYDY4Suu4/Lmhh2quKBU7BHGOtKwu9o="; // 1. 解码Base64格式的密文 $encryptedRaw = base64_decode($encrypted); // 2. 提取OpenSSL格式中的salt和实际密文 // 格式规则:Salted__(8字节) + 8字节salt + 密文内容 $salt = substr($encryptedRaw, 8, 8); $ciphertext = substr($encryptedRaw, 16); // 3. 用PBKDF2派生密钥,匹配CryptoJS默认参数:SHA-1、1000次迭代、32字节密钥(AES-256) $derivedKey = hash_pbkdf2('sha1', $key, $salt, 1000, 32, true); // 4. 执行解密,OPENSSL_RAW_DATA表示输入为二进制密文 $plaintext = openssl_decrypt($ciphertext, 'AES-256-CBC', $derivedKey, OPENSSL_RAW_DATA, $iv); echo $plaintext; ?>
关键逻辑说明
- 密钥派生匹配:CryptoJS默认使用PBKDF2,参数为SHA-1哈希、1000次迭代、生成32字节密钥(对应AES-256),PHP的
hash_pbkdf2必须完全匹配这些参数才能生成和加密时一致的密钥。 - 密文格式解析:OpenSSL格式的密文开头固定为
Salted__,后续8字节是加密时生成的随机salt,必须提取该salt用于密钥派生,不能忽略。 - IV一致性:解密时必须使用和加密时完全相同的IV,你的IV是16字节,符合AES-CBC的要求(IV长度需等于分组长度,AES分组为16字节)。
可选优化方案(调整加密逻辑)
如果不想使用PBKDF2密钥派生,可以在CryptoJS中直接传入WordArray类型的密钥,避免自动生成salt:
encrypt(key, iv, value){ // 将字符串密钥和IV转为WordArray(UTF-8编码) const keyBytes = CryptoJS.enc.Utf8.parse(key); const ivBytes = CryptoJS.enc.Utf8.parse(iv); // 加密时直接使用原始密钥,不派生 const encrypted = CryptoJS.AES.encrypt(value, keyBytes, { iv: ivBytes }); // 仅输出密文的Base64(不包含salt) return encrypted.ciphertext.toString(CryptoJS.enc.Base64); }
此时PHP代码可简化为:
<?php $iv = "048eb25d7a45ff00"; $key = "feda4f2f67e7aa96"; $encrypted = "你的密文"; $plaintext = openssl_decrypt(base64_decode($encrypted), 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); echo $plaintext; ?>
内容的提问来源于stack exchange,提问作者fagbemi ayodele
相关产品推荐
相关产品推荐

