【问题标题】:PHP openssl_encrypt in JavaScript with CryptoJSPHP openssl_encrypt 在 JavaScript 中使用 CryptoJS
【发布时间】:2017-07-13 13:47:57
【问题描述】:

我在 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”参数。

【问题讨论】:

    标签: javascript encryption encoding cryptojs


    【解决方案1】:

    您的“密钥”长度为 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,该 IV 编码为 Hex 时的长度是其两倍。使用前应从 Hex 解码。

    IV 必须是不可预测的(阅读:随机)。不要使用静态 IV,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定之前发送相同消息前缀的时间。 IV 不是秘密,因此您可以将其与密文一起发送。通常,它只是简单地添加到密文中,并在解密之前被切掉。

    【讨论】:

    • 谢谢你的回答,我明天试试,IV 不是静态的,而是与加密值一起发送的,我只是想让这个例子的所有内容尽可能静态.
    • 是的,谢谢你的澄清,PHP 正在截断密钥 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 2019-06-16
    • 2014-12-24
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    相关资源
    最近更新 更多