使用CryptoJS和PHP进行AES加密

时间:2018-04-27 09:36:12

标签: javascript php aes cryptojs

我想使用JavaScript实现AES加密。使用AES CBC模式。我已经设法用PHP做到了。它看起来像:

 public function encrypt($value) {
        if (empty($value)) {
          return $value;
        }
        $value = Unicode::convertToUtf8($value, 'UTF-8');
        if ($key = $this->getEncryptionKey()) {
          // Generates from key 1st 16 bytes.
          $iv = mb_substr($key, 0, 16);
          //encrypt message with key
          $message = openssl_encrypt($value, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
          return base64_encode($message);
        }
    }

    public function getEncryptionKey() {
        $key = 'secret';
        $key = Unicode::convertToUtf8($key, 'UTF-8');

        // Make sure the key is the correct size.
        if (strlen($key) < 32) {
          $key = str_pad($key, 32, "\0");
        }

        if (strlen($key) > 32) {
          $key = mb_substr($key, 0, 32);
        }

        return $key;
    }

如果我给$ value = retest2;它给了我你知道输出

我知道这是对的,我尝试使用C#也得到了相同的结果。但是当我尝试使用JavaScript复制它时,我无法生成相同的PHP输出。以下是我尝试过的javascript代码:

const message = utf8.encode('retest2');
const password = utf8.encode('secret').padEnd(32, '\0');
const key =  CryptoJS.enc.Hex.parse(password);
const iv =  CryptoJS.enc.Hex.parse(password.substring(0, 16));

const encrypted = CryptoJS.AES.encrypt(message, key, {
    iv: iv
});
console.log(btoa(encrypted.toString()));

使用相同的值,我得到 dzd4bjNwenduQT09 。 我也在这里读过关于同一主题的其他类似问题,但我似乎无法弄清楚我哪里出错了? 谢谢!

2 个答案:

答案 0 :(得分:0)

这些应该是评论,但空间有限......

您不应该使用从它派生的密钥或数据作为初始化向量。

  

我知道这是对的,我也尝试使用C#

您应该向我们展示代码。

您的openssl调用调用key derivation function从您在第三个参数中传递的数据创建(更好?)加密密钥。 OTOH,在crypto.js中有no implicit key derivation

答案 1 :(得分:0)

正如@symcbean所说,

  

您不应该使用从中获取的密钥或数据作为您的密钥   初始化向量。

我认为,你没有选择,你必须使用从它派生的密钥或数据作为初始化向量。

几个月前,我遇到了完全相同的情况,我做了类似的事情,

const message = 'retest2';
let password = 'secret';
if (password.length < 32) {
    password = password.padEnd(32, '\0');
}
const iv = CryptoJS.enc.Utf8.parse(password.substring(0, 16));
password = CryptoJS.enc.Utf8.parse(password);
const encrypted = CryptoJS.AES.encrypt((message), (password), {
    iv: iv
});
console.log(CryptoJS.enc.Base64.stringify(encrypted.ciphertext));