PHP 的 AES 加密问题
为什么 PHP AES 解密 CBC 模式 iv 可以为空呢? 用 Java 去解密没有 iv 根本解密不出来啊,有什么办法解决?
为什么 PHP AES 解密 CBC 模式 iv 可以为空呢? 用 Java 去解密没有 iv 根本解密不出来啊,有什么办法解决?
似乎不是的,参见: https://blog.lancitou.net/how-to-generate-key-and-iv-in-openssl-aes/
OPENSSL AES 算法中的 IV 是这样来的:
“`
hash1_128 = MD5(Passphrase + Salt)
hash2_128 = MD5(hash1_128 + Passphrase + Salt)
hash3_128 = MD5(hash2_128 + Passphrase + Salt)
Key = hash1_128 + hash2_128
IV = hash3_128
“`
另外,@youngs 不知道你用的是 PHP 什么版本,用的哪个函数在解 AES,最好有代码或者伪代码……
也就 ECB 不需要 IV (千万别用)
感觉你这问题和这有些关系 你可以使用相同的 iv(例如全 0 值) 打印解密后的原始数据看看一不一样
有个关键问题是:你的密文是用 PHP 加密的吗?
我刚才测试了 PHP 下加密的时候 iv 参数不能为空,即 mcrypt_generic_init() 函数第 3 个参数不能为空,一定要设置的,而根据官网文档的说法是建议设置为全 0 值(长度根据 mcrypt_enc_get_iv_size 来设置)。
所以现在问题的关键是你的密文是怎么加密的,openssl ?还是其他语言?
function Encrypt_aes2(word, privateKey) {
var data = word;
var key = CryptoJS.enc.Utf8.parse(‘1111111111111111’);
var iv = CryptoJS.enc.Utf8.parse(”);
//加密
var encrypted = CryptoJS.AES.encrypt(data, key, { iv: iv, mode: CryptoJS.mode.CBC });
console.log(‘encrypted.toString()’, encrypted.toString())
// 这里是解密
console.log(‘解密’ ,CryptoJS.AES.decrypt(encrypted.toString(), key, { iv: iv, mode: CryptoJS.mode.CBC }).toString(CryptoJS.enc.Utf8))
return encrypted.toString();
}
好了,话题终结了。
看了下 CryptoJs 源码,和我在本帖 4 回复的猜想一样,如果你的 key 是个字符串,那么 CryptoJs 底层会用和 Openssl 兼容的函数来生成 iv:根据你的 key 和一个随机的 salt 经过若干次 md5 后生成的,每次 encrypt 的 iv 都不一样,具体方式见我 4 的伪代码。
那么,怎么取到 CryptoJS 每次调用 AES.encrypt 时的 iv 呢?很简单……
// Encrypt
var ct = CryptoJS.AES.encrypt(‘my message’, ‘secret key 123’);
var saltHex = ct.salt.toString(); // random salt
var ctHex = ct.ciphertext.toString(); // actual ciphertext
var ivHex = ct.iv.toString(); // generated IV
console.log(saltHex);
console.log(ctHex);
console.log(ivHex);
你可以试试用打印出来的 iv 到 PHP 或者 Java 里面去解解看。
// Encrypt
var ct = CryptoJS.AES.encrypt(‘my message’, ‘secret key 123’);
var saltHex = ct.salt.toString(); // random salt
var ctHex = ct.ciphertext.toString(); // actual ciphertext
var ivHex = ct.iv.toString(); // generated IV
console.log(saltHex);
console.log(ctHex);
console.log(ivHex);
// Decrypt
var bytes = CryptoJS.AES.decrypt(ct.toString(), ‘secret key 123’, { iv: ct.iv, mode: CryptoJS.mode.CBC });
var originalText = bytes.toString(CryptoJS.enc.Utf8);
console.log(originalText);
如果,你现在想解密之前已经加密出来的密文,那么就稍微麻烦一些:
首先,加密出来的密文是 base64 的,你 base64_decode 之后会发现开头是 “Salted__”这样的,然后紧跟着的 8 个字节就是 salt 了,然后根据我 4 的伪代码,Passphrase (即 key ) 和 Salt 你都有了,可以自己算出 iv 。
这个部分你自己实现即可,18 点过了,我下班回家了…… 2333