我在JavaScript中生成与第三方PHP服务器中提供的相同密文有问题。服务器端使用简单的单行生成密钥,但我找不到在JavaScript客户端中执行相同操作的方法。
我决定使用来自other SO answers 的CryptoJS库,我确实生成了一个密文,但它与PHP服务器的密文不同。
PHP加密:
echo openssl_encrypt("5905","AES-256-CBC","FbcCY2yCFBwVCUE9R+6kJ4fAL4BJxxjdRcqy5rHVLwU=",NULL,"e16ce913a20dadb8");
// phgygAJB3GA0sa4D9k/d8A==
我尝试过Stack Overflow的几个解决方案,但无法创建相同的密文。
此外,PHP单行中的参数“AES-256-CBC”困扰我:我知道AES是什么,但我不知道256或CBC部分是什么,我不知道在哪里设置那些在CryptoJS方面。
我目前的尝试:
var key = 'FbcCY2yCFBwVCUE9R+6kJ4fAL4BJxxjdRcqy5rHVLwU=';
var iv = 'e16ce913a20dadb8';
var encrypted = CryptoJS.AES.encrypt("5905", CryptoJS.enc.Hex.parse(key), { iv: CryptoJS.enc.Hex.parse(iv) });
var r1 = encrypted.ciphertext.toString(); // def44f8822cfb3f317a3c5b67182b437
var r2 = CryptoJS.enc.Base64.stringify(encrypted.ciphertext) // 3vRPiCLPs/MXo8W2cYK0Nw==
我的猜测是我在JavaScript中缺少“256”和“CBC”参数。
答案 0 :(得分:3)
你的"键"长度为44个字符,也相当于PHP中的44个字节。这不是有效的密钥大小。 AES仅支持16,24和32字节密钥。无论如何,这个"关键"将被截断为32字节。所以你在PHP中的实际关键是:
"FbcCY2yCFBwVCUE9R+6kJ4fAL4BJxxjd"
您的IV长度为16个字符(和字节),因此它具有正确的长度并按原样使用。
这也是您可以将CryptoJS中的密钥和IV视为字符串的原因:
CryptoJS.AES.encrypt("5905", CryptoJS.enc.Utf8.parse(key), { iv: CryptoJS.enc.Utf8.parse(iv) });
但是正确的方法是从Base64解码密钥并生成一个正确的IV,当编码为Hex时,它是两倍长。它应该在使用前从Hex解码。
IV必须是不可预测的(读:随机)。不要使用静态IV,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定何时发送相同的消息前缀。 IV不是秘密,因此您可以将其与密文一起发送。通常,它只是在密文之前预先填写并在解密之前切掉。