I am trying to send AES encrypted messages between javascript and php using a shared secret. In Javascript I am using the CryptoJS library. In php, I am using mycrypt. I am trying to construct an encrypted message in javascript and then decrypt it in php using the shared secret. I can encrypt and decrypt a message in Javascript. I can encrypt and decrypt the same message in php - but the encryption is not the same between the two.
The Javascript
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
alert(encrypted);
Gives
U2FsdGVkX18+k3pba4l4MbGZfmDjMc1yQ6uj1fg+BGo=
In 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"
);
}
The output is
Encrypted: iqJ0R5ahRP7GpWKtW7+OBSCGnudDr99VbJC36OQlmgE=
Decrypted: Message
My question is, why are these not the same?
It would be a crypographic catastrophy if they would be the same...
However: Using the way you used your PHP Encryption (using EBC mode) you will always get the same result. You can see why this is a problem by looking at the tux pciture at http://en.wikipedia.org/wiki/Cipher_block_chaining#Electronic_codebook_.28ECB.29
CryptoJS seems to use CBC as a default block cipher mode (at least they say so in https://code.google.com/p/crypto-js/#Block_Modes_and_Padding), which has a random initial vector. This is better than CBC.
The result should be the same, if you use the same cipher, the same block cipher mode (e.g. CBC) and the same key and IV - and of course the same plaintext - the comments indicate that there also might be a unicode issue.
Additionally the MCRYPT_RIJNDAEL_256 is not AES. AES has a BLOCK size of 16 byte - AES-128 has a KEY size of 16 byte, AES-256 has a KEY size of 32 byte. MCRYPT_RIJNDAEL_256 has a BLOCK size of 32 byte - that's a big difference.
One last note: It is not enough to encrypt data! You must also authenticate it, by either using a HMAC or by using an authenticated block cipher mode like GCM - if you don't do this you may be vulnerable to at least a padding oracle attack: http://en.wikipedia.org/wiki/Padding_oracle_attack
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments