2014-02-15 233 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