在CryptoJS中加密并在mCrypt中解密不能正常工作

时间:2014-10-22 22:06:15

标签: javascript php encryption cryptojs

在过去的两天里,我一直在努力解决我最初想要实现的问题。

我需要一种非常简单的非安全方式来通过AJAX发送密码并将其解密到服务器端

我使用CryptoJS中的AES:

JS加密

    msg = "message";
    var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f');
    var iv  = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');
    var encrypted = CryptoJS.AES.encrypt(msg, key, { iv: iv });

    var data_base64 = encrypted.ciphertext.toString(CryptoJS.enc.Base64); 
    var iv_base64   = encrypted.iv.toString(CryptoJS.enc.Base64);       
    var key_base64  = encrypted.key.toString(CryptoJS.enc.Base64);

    console.log(data_base64,iv_base64,key_base64) //If I use these keys in the PHP decryption it works

    return encrypted.toString();

... 使用mCrypt进行PHP解密

$encrypted = "f82126a59b76d86946a013d9f575d0d4"; //this is what the JS function above returned.
$key = "000102030405060708090a0b0c0d0e0f"; //same key as in JS function
$iv = "101112131415161718191a1b1c1d1e1f"; //same IV as in JS function

$plaintext = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CBC, $iv ), "\t\0 " );

echo "Original string : " . $encrypted . "<br />\n"; 
echo "Decrypted string : " . $plaintext . "<br />\n";

由于我使用相同的IVkey来加密,我希望这可以解密就好了。但是我似乎错过了一些东西,因为我仍然在plaintext.

中看到了胡言乱语

修改

  

似乎AES的整个目的是keys和。{   我必须使用的IV是由CryptoJS输出的(参见console.log中的内容)   JS功能)。如果我使用那些功能似乎运行得很好。   但实际上我并不想这样,因为这些键是动态的   因此,每当我运行他们改变的JS函数时生成。我只是   需要在客户端和服务器之间使用共享私钥   加密/解密并且是静态的。就这么简单。

2 个答案:

答案 0 :(得分:0)

您的密钥是128位($ key的长度是32个十六进制字符,表示16个字节或128位)。但是,在您的mcrypt_decrypt()调用中,您告诉PHP使用带有256位密钥的MCRYPT_RIJNDAEL_256。请尝试使用MCRYPT_RIJNDAEL_128。通常,密码应该适应传递密钥的长度,但可能是PHP使用空字节填充密钥以使用256位加密。

其次,在PHP中,mcrypt_decrypt设置为使用CBC模式(参见MCRYPT_MODE_CBC)。您没有指定CryptoJS应该使用哪种模式。幸运的是,根据CryptoJS的文档,CBC模式是默认使用的模式;但是,既然您正在编写可移植代码,那么您应该考虑明确这一点。

修改

如果它告诉您密钥太长,那是因为您没有打包它们。您给PHP一个长度为32字节(256位)的十六进制编码字符串,这不是您的关键!要获取您需要执行的二进制数据:

$key = pack('H*', "000102030405060708090a0b0c0d0e0f");
$iv = pack('H*', "101112131415161718191a1b1c1d1e1f");

pack('H*', $str);函数将十六进制表示转换为二进制字符串。

答案 1 :(得分:0)

MCRYPT_RIJNDAEL_256与AES不同。 256与密码的块大小有关,而不是密钥大小。

快速历史课程 - AES是一项最终由称为Rijndael的算法赢得的竞赛。 Rinjdael是为几种块大小(128,160,192,224和256位)定义的密码。但是,对于AES,仅选择了128位块大小。

当您使用需要IV的模式(如CBC模式)时,块大小定义IV的大小。因此,对于AES,无论密钥大小如何,您都需要128位IV。支持的密钥大小为128,192或256位。

在PHP中,可以使用密码MCRYPT_RIJNDAEL_128来使用AES。