使用 PHP 加密;使用 CryptoJS 解密

Encrypting with PHP; decrypting with CryptoJS

本文关键字:使用 解密 CryptoJS 加密 PHP      更新时间:2023-09-26

我在使用PHP加密的CryptoJS解密数据时遇到了一些问题。也许有人可以建议我哪里出错了?

我加密如下:

  1. 获取散列密码
  2. 以 (0,16) 的子字符串为键
  3. 加密 (MCRYPT_RIJNDAEL_128)
  4. 将密文编码为 base64

解密时,我也会这样做:

  1. 获取散列密码
  2. 以 (0,16) 的子字符串为键
  3. Base64 解码密文
  4. 解密

.PHP:

public function encrypt($input, $key) {
    $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
    $input = $this->_pkcs5_pad($input, $size);
    $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
    $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
    mcrypt_generic_init($td, $key, $iv);
    $data = mcrypt_generic($td, $input);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    $data = base64_encode($data);
    return $data;
}

JavaScript:

function decrypt(ciphertext, hashedPsw) {
        var key =  hashedPsw.substring(0, 16);
        var key = CryptoJS.enc.Hex.parse(key);
        var options = { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7, keySize:128 / 32 };
        ciphertext = CryptoJS.enc.Base64.parse(ciphertext);
        var decrypted = CryptoJS.AES.decrypt(ciphertext, key);
        return decrypted;
    }

CryptoJS decrypt函数需要一个包含 WordArray 而不是 WordArray 本身的对象,因此您需要使用:

var decrypted = CryptoJS.AES.decrypt({ ciphertext: ciphertext }, key, options);

您还需要将选项传递给 decrypt 函数。否则,CryptoJS不会知道你想使用ECB模式。


安全

不要使用欧洲央行模式!它在语义上不安全。您至少应该将CBC模式与随机IV一起使用。IV 不需要是秘密的,因此您只需将其附加到密文中即可。

然后,您应该验证您的密文。这可以通过GCM或EAX等经过身份验证的模式来完成,但它们不是由mcrypt或CryptoJS提供的。下一个最好的办法是使用加密然后MAC方案,其中您在密文上使用强密钥哈希函数(如HMAC-SHA256),以使攻击者无法在您不知情的情况下更改密文。

我刚刚在上一个线程中发现了答案: 事实证明,问题出在关键编码上。