javascript - 使用 CryptoJS 在 JavaScript 中进行 AES 加密/解密

标签 javascript php security encryption cryptography

我正在尝试使用共享 key 在 javascript 和 php 之间发送 AES 加密消息。在 Javascript 中,我使用 CryptoJS 库。在 php 中,我使用 mycrypt。我正在尝试在 javascript 中构造一条加密消息,然后使用共享 key 在 php 中对其进行解密。我可以用 JavaScript 加密和解密消息。我可以在 php 中加密和解密相同的消息 - 但两者之间的加密不同。

Javascript

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
alert(encrypted);

给予

U2FsdGVkX18+k3pba4l4MbGZfmDjMc1yQ6uj1fg+BGo=

在 PHP 中

<?php
$Pass = "Secret Passphrase";
$Clear = "Message";

$crypted = fnEncrypt($Clear, $Pass);
echo "Encrypted: ".$crypted."</br>";

$newClear = fnDecrypt($crypted, $Pass);
echo "Decrypted: ".$newClear."</br>";

function fnEncrypt($sValue, $sSecretKey) {
return rtrim(
        base64_encode(
                mcrypt_encrypt(
                        MCRYPT_RIJNDAEL_256,
                        $sSecretKey, $sValue,
                        MCRYPT_MODE_ECB,
                        mcrypt_create_iv(
                                mcrypt_get_iv_size(
                                        MCRYPT_RIJNDAEL_256,
                                        MCRYPT_MODE_ECB
                                ),
                                MCRYPT_RAND
                        )
                )
        ),"\0"
);
}

function fnDecrypt($sValue, $sSecretKey) {
return rtrim(
        mcrypt_decrypt(
                MCRYPT_RIJNDAEL_256,
                $sSecretKey,
                base64_decode($sValue),
                MCRYPT_MODE_ECB,
                mcrypt_create_iv(
                        mcrypt_get_iv_size(
                                MCRYPT_RIJNDAEL_256,
                                MCRYPT_MODE_ECB
                        ),
                        MCRYPT_RAND
                )
        ),"\0"
);
}

输出为

加密:iqJ0R5ahRP7GpWKtW7+OBSCGnudDr99VbJC36OQlmgE=

解密:消息

我的问题是,为什么这些不一样?

最佳答案

如果它们相同,那将是一场密码学灾难......

但是:使用您使用 PHP 加密的方式(使用 EBC 模式),您将始终得到相同的结果。您可以通过查看 http://en.wikipedia.org/wiki/Cipher_block_chaining#Electronic_codebook_.28ECB.29 中的燕尾服图片来了解为什么这是一个问题。

CryptoJS 似乎使用 CBC 作为默认分组密码模式(至少他们在 https://code.google.com/p/crypto-js/#Block_Modes_and_Padding 中这么说),它具有随机初始向量。这比 CBC 更好。

如果您使用相同的密码、相同的分组密码模式(例如 CBC)以及相同的 key 和 IV - 当然还有相同的明文 - 注释表明也可能存在 unicode,结果应该是相同的问题。

此外,MCRYPT_RIJNDAEL_256 不是 AES。 AES 的 block 大小为 16 字节 - AES-128 的 key 大小为 16 字节,AES-256 的 key 大小为 32 字节。 MCRYPT_RIJNDAEL_256 的 block 大小为 32 字节 - 这是一个很大的差异。

最后一点:仅加密数据是不够的!您还必须通过使用 HMAC 或使用经过身份验证的 block 密码模式(如 GCM)对其进行身份验证 - 如果您不这样做,您可能至少容易受到填充预言机攻击:http://en.wikipedia.org/wiki/Padding_oracle_attack

关于javascript - 使用 CryptoJS 在 JavaScript 中进行 AES 加密/解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21804911/

相关文章:

php - Mysql自动更新事件

vb.net - 解码编码变量

http header 的安全性

javascript - Meteor:每次集合更改时如何触发命令?

javascript - 循环遍历对象的键,然后循环遍历值(因为它们是数组)

javascript - 如何提交未选中的复选框

security - 为什么在生产中使用使用 MakeCert 工具制作的证书不好?

javascript - 执行一些代码,然后进入交互 Node

php - 如何使用 php 中 while 循环以外的循环从 mysql db 检索数据?

php - 如何重用 Dusk 测试浏览器实例?