2014-02-15 195 views
1

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

的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 =

解密:消息

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

+0

php is ascii and js是unicode,所以即使这些字符串看起来像是具有相同的二进制模式,但它们不会,并且当您混合这些位时,差异就会变得明显。 PHP可以做unicode了吗? – dandavis

+1

php在unicode上基本没有声音。一个字符串只是一个“字符串”(哈)的字符。不管这些字符是1byte-per-char ascii还是多字节像utf16或utf8都不是PHP的工作。 –

回答

1

这将是一个crypographic catastrophy如果他们是相同的...

不过:用你用你的PHP加密方式(使用EBC模式),你总是会得到相同的结果。你可以看到为什么这是通过在http://en.wikipedia.org/wiki/Cipher_block_chaining#Electronic_codebook_.28ECB.29

CryptoJS看晚礼服pciture问题似乎使用CBC作为默认块加密模式(至少他们在https://code.google.com/p/crypto-js/#Block_Modes_and_Padding这么说),它具有随机初始向量。这比CBC好。

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

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

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

+0

很好的参考资料,对帮助我掌握学习曲线非常有帮助。我决定使用GibberishAES,它具有很好的协调性的javascript和php库。 – anthonyc