admin管理员组文章数量:1194384
I'm encrypting my user password in JavaScript like this:
var encryptedPassword = CryptoJS.AES.encrypt(password, "Secret Passphrase");
It works fine but now I'm trying to decrypt in PHP on the server side like this:
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
$decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, "Secret Passphrase", base64_decode($password), MCRYPT_MODE_CBC, $iv);
it doesn't works at all, the decrypted password string looks very strange:
string(64) ">�OX2MS��댗v�<$�ʕ��i�̄��_��P���\�կ=�_6(�m����,4WT7��a"
Here is the current state of my code in JavaScript after the helpful comments:
var encryptedPassword = CryptoJS.AES.encrypt(password, "Secret Passphrase");
var ivHex = encryptedPassword.iv.toString();
var ivSize = encryptedPassword.algorithm.ivSize; // same as blockSize
var keySize = encryptedPassword.algorithm.keySize;
var keyHex = encryptedPassword.key.toString();
var saltHex = encryptedPassword.salt.toString(); // must be sent
var openSslFormattedCipherTextString = encryptedPassword.toString(); // not used
var cipherTextHex = encryptedPassword.ciphertext.toString(); // must be sent
I am sending saltHex and CipherTextHex to the PHP server and I'm using mcrypt_decrypt() like this:
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), $saltHex);
$decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, "Secret Passphrase", base64_decode($cipherTextHex), MCRYPT_MODE_CBC, $iv);
It still does't work with this updated code.
Can someone help me to decrypt properly with mcrypt_decrypt() PHP function for a simple AES encryption method ? I'm sure I am doing something wrong with the cipher, mcrypt mode and the IV parameters inside my mcrypt_decrypt() method. Thanks if you know.
I'm encrypting my user password in JavaScript like this:
var encryptedPassword = CryptoJS.AES.encrypt(password, "Secret Passphrase");
It works fine but now I'm trying to decrypt in PHP on the server side like this:
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
$decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, "Secret Passphrase", base64_decode($password), MCRYPT_MODE_CBC, $iv);
it doesn't works at all, the decrypted password string looks very strange:
string(64) ">�OX2MS��댗v�<$�ʕ��i�̄��_��P���\�կ=�_6(�m����,4WT7��a"
Here is the current state of my code in JavaScript after the helpful comments:
var encryptedPassword = CryptoJS.AES.encrypt(password, "Secret Passphrase");
var ivHex = encryptedPassword.iv.toString();
var ivSize = encryptedPassword.algorithm.ivSize; // same as blockSize
var keySize = encryptedPassword.algorithm.keySize;
var keyHex = encryptedPassword.key.toString();
var saltHex = encryptedPassword.salt.toString(); // must be sent
var openSslFormattedCipherTextString = encryptedPassword.toString(); // not used
var cipherTextHex = encryptedPassword.ciphertext.toString(); // must be sent
I am sending saltHex and CipherTextHex to the PHP server and I'm using mcrypt_decrypt() like this:
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), $saltHex);
$decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, "Secret Passphrase", base64_decode($cipherTextHex), MCRYPT_MODE_CBC, $iv);
It still does't work with this updated code.
Can someone help me to decrypt properly with mcrypt_decrypt() PHP function for a simple AES encryption method ? I'm sure I am doing something wrong with the cipher, mcrypt mode and the IV parameters inside my mcrypt_decrypt() method. Thanks if you know.
Share Improve this question edited Dec 28, 2014 at 15:11 Nizar B. asked Dec 28, 2014 at 14:17 Nizar B.Nizar B. 3,1189 gold badges41 silver badges56 bronze badges 12 | Show 7 more comments3 Answers
Reset to default 18The problem is that in the CryptoJS code a password is used to derive the key and the IV to be used for AES encryption, but mcrypt only uses the key to encrypt/decrypt. This information needs to be passed to php. Since you don't want to transmit the password, you have to derive the key and IV in the same way in php.
The following code derives the key and IV from a password and salt. It is modeled after the code in my answer here (for more information).
function evpKDF($password, $salt, $keySize = 8, $ivSize = 4, $iterations = 1, $hashAlgorithm = "md5") {
$targetKeySize = $keySize + $ivSize;
$derivedBytes = "";
$numberOfDerivedWords = 0;
$block = NULL;
$hasher = hash_init($hashAlgorithm);
while ($numberOfDerivedWords < $targetKeySize) {
if ($block != NULL) {
hash_update($hasher, $block);
}
hash_update($hasher, $password);
hash_update($hasher, $salt);
$block = hash_final($hasher, TRUE);
$hasher = hash_init($hashAlgorithm);
// Iterations
for ($i = 1; $i < $iterations; $i++) {
hash_update($hasher, $block);
$block = hash_final($hasher, TRUE);
$hasher = hash_init($hashAlgorithm);
}
$derivedBytes .= substr($block, 0, min(strlen($block), ($targetKeySize - $numberOfDerivedWords) * 4));
$numberOfDerivedWords += strlen($block)/4;
}
return array(
"key" => substr($derivedBytes, 0, $keySize * 4),
"iv" => substr($derivedBytes, $keySize * 4, $ivSize * 4)
);
}
The salt is generated during encryption in CryptoJS and needs to be sent to php with the ciphertext. Before invoking evpKDF
the salt has to be converted to a binary string from hex.
$keyAndIV = evpKDF("Secret Passphrase", hex2bin($saltHex));
$decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,
$keyAndIV["key"],
hex2bin($cipherTextHex),
MCRYPT_MODE_CBC,
$keyAndIV["iv"]);
If only encryptedPassword.toString()
was sent to the server, then it is necessary to split the salt and actual ciphertext before use. The format is a proprietary OpenSSL-compatible format with the first 8 bytes being "Salted__", the next 8 bytes being the random salt and the rest is the actual ciphertext. Everything together is Base64-encoded.
function decrypt($ciphertext, $password) {
$ciphertext = base64_decode($ciphertext);
if (substr($ciphertext, 0, 8) != "Salted__") {
return false;
}
$salt = substr($ciphertext, 8, 8);
$keyAndIV = evpKDF($password, $salt);
$decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,
$keyAndIV["key"],
substr($ciphertext, 16),
MCRYPT_MODE_CBC,
$keyAndIV["iv"]);
// unpad (PKCS#7)
return substr($decryptPassword, 0, strlen($decryptPassword) - ord($decryptPassword[strlen($decryptPassword)-1]));
}
The same can be achieved with the OpenSSL extension instead of Mcrypt:
function decrypt($ciphertext, $password) {
$ciphertext = base64_decode($ciphertext);
if (substr($ciphertext, 0, 8) != "Salted__") {
return false;
}
$salt = substr($ciphertext, 8, 8);
$keyAndIV = evpKDF($password, $salt);
$decryptPassword = openssl_decrypt(
substr($ciphertext, 16),
"aes-256-cbc",
$keyAndIV["key"],
OPENSSL_RAW_DATA, // base64 was already decoded
$keyAndIV["iv"]);
return $decryptPassword;
}
/**
*-------------PHP code example-----------------
*/
/**
* Decrypt data from a CryptoJS json encoding string
*
* @param mixed $passphrase
* @param mixed $jsonString
* @return mixed
*/
function cryptoJsAesDecrypt($passphrase, $jsonString){
$jsondata = json_decode($jsonString, true);
$salt = hex2bin($jsondata["s"]);
$ct = base64_decode($jsondata["ct"]);
$iv = hex2bin($jsondata["iv"]);
$concatedPassphrase = $passphrase.$salt;
$md5 = array();
$md5[0] = md5($concatedPassphrase, true);
$result = $md5[0];
for ($i = 1; $i < 3; $i++) {
$md5[$i] = md5($md5[$i - 1].$concatedPassphrase, true);
$result .= $md5[$i];
}
$key = substr($result, 0, 32);
$data = openssl_decrypt($ct, 'aes-256-cbc', $key, true, $iv);
return json_decode($data, true);
}
/**
* Encrypt value to a cryptojs compatiable json encoding string
*
* @param mixed $passphrase
* @param mixed $value
* @return string
*/
function cryptoJsAesEncrypt($passphrase, $value){
$salt = openssl_random_pseudo_bytes(8);
$salted = '';
$dx = '';
while (strlen($salted) < 48) {
$dx = md5($dx.$passphrase.$salt, true);
$salted .= $dx;
}
$key = substr($salted, 0, 32);
$iv = substr($salted, 32,16);
$encrypted_data = openssl_encrypt(json_encode($value), 'aes-256-cbc', $key, true, $iv);
$data = array("ct" => base64_encode($encrypted_data), "iv" => bin2hex($iv), "s" => bin2hex($salt));
return json_encode($data);
}
$encrypted = '{"ct":"nPfd1U0y9o2hRCdwJK6XkM1E01wa1ZjMu3eAzGjUD60=","iv":"2abda27fc571cf74e6efc1ba564801f9","s":"813a340e805f54ae"}';
$key = "123456";
$decrypted = cryptoJsAesDecrypt($key, $encrypted);
/* -------------Javascript code example-----------------*/
var CryptoJSAesJson = {
stringify: function (cipherParams) {
var j = {ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)};
if (cipherParams.iv) j.iv = cipherParams.iv.toString();
if (cipherParams.salt) j.s = cipherParams.salt.toString();
return JSON.stringify(j);
},
parse: function (jsonStr) {
var j = JSON.parse(jsonStr);
var cipherParams = CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Base64.parse(j.ct)});
if (j.iv) cipherParams.iv = CryptoJS.enc.Hex.parse(j.iv)
if (j.s) cipherParams.salt = CryptoJS.enc.Hex.parse(j.s)
return cipherParams;
}
}
var key = "123456";
var encrypted = CryptoJS.AES.encrypt(JSON.stringify("value to encrypt"), key, {format: CryptoJSAesJson}).toString();
console.log(encrypted);
var decrypted = JSON.parse(CryptoJS.AES.decrypt(encrypted, key, {format: CryptoJSAesJson}).toString(CryptoJS.enc.Utf8));
console.log("decryyepted: "+decrypted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
You can't decrypt with a random initialisation vector - you need to use the same IV the data was encrypted with. Also, IIRC, AES defaults to an 8 bit representation of the encrypted data which will need to be handled carefully in transfer over HTTP.
本文标签: Encryption in JavaScript and decryption with PHPStack Overflow
版权声明:本文标题:Encryption in JavaScript and decryption with PHP - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738443127a2087066.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
JavaScript
and decrypt inPHP
, Because you can do encrypt and decrypt inPHP
– user4314601 Commented Dec 28, 2014 at 14:21encryptedPassword
is transmitted, because it may be encoded ito it. CryptoJS uses an OpenSSLFormatter. You should look into the code of CryptoJS. – Artjom B. Commented Dec 28, 2014 at 14:32