CryptoJS extra parameter in AES Encrypt. How to replicate with PHP? [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am trying to replicate the following CryptoJS 3.1.2 code with PHP 5.4.4 :
var plaintext = 'test';
var key = CryptoJS.enc.Utf8.parse('9rIY8vV8DdOKx3m6JocjEaObhhYc2NfY');
var iv = CryptoJS.enc.Utf8.parse('r0dkbnVQhklNeUGA');
var encrypted = CryptoJS.AES.encrypt(plaintext, 'euhe68vjdr1aX4F091c7aCggSMBf0A7M', key,{iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});
I have found several questions dealing with that problem, but none of them had that extra parameter in encrypt() between plaintext and key.
The CryptoJS wiki does not mention this parameter at all.
And yet, it works. I can decrypt with this :
var decrypted = CryptoJS.AES.decrypt(encrypted, 'euhe68vjdr1aX4F091c7aCggSMBf0A7M', key, {iv: iv});
If I omit 'euhe68vjdr1aX4F091c7aCggSMBf0A7M' in the decrypt() call, it won't work.
So that parameter really does something. But what? Is is a hash, a salt?
Does anybody know how I can replicate this specific encryption process with PHP?
I can not modify this JS code in any way.
The code is on a login page and is used to encrypt credentials before they are sent to the server.
I am trying to use PHP-cURL to submit credentials to that server from the command line, which is why I need to reproduce this encryption process.
Update: thanks to Jim's answer, I now have the proper JavaScript, now I need help with replicating the code in PHP
Here is the JS :
var plaintext = 'test';
var key = 'euhe68vjdr1aX4F091c7aCggSMBf0A7M';
var iv = CryptoJS.enc.Utf8.parse('r0dkbnVQhklNeUGA');
var encrypted = CryptoJS.AES.encrypt(plaintext, key, key,{iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7})
encrypted equals U2FsdGVkX1+ZujoXKqDHcO+4N1QO+Nv1KHUMFjZos1s=
Here is the decryption:
var decrypted = CryptoJS.AES.decrypt(encrypted, key);
decrypted equals test
I have tried many different ways to replicate the encryption with PHP, but none of them gives a a string I can decode with the above JS.
For instance, using this AES_Encryption class, I tried the following code :
$key = 'euhe68vjdr1aX4F091c7aCggSMBf0A7M';
$iv = 'r0dkbnVQhklNeUGA';
$message = 'test';
$AES = new AES_Encryption($key, $iv, PKCS7);
$encrypted = $AES->encrypt($message);
$decrypted = $AES->decrypt($encrypted);
$base64_encrypted = base64_encode('Salted__'.$encrypted);
I end up with U2FsdGVkX18eEv+TnigBEKGJL8t/V1Hm instead of U2FsdGVkX1+ZujoXKqDHcO+4N1QO+Nv1KHUMFjZos1s=
Note that both strings start the same way, thanks to the 'Salted__' prefix I added (since CryptoJS seems to do the same thing).
I tried similar code with phpseclib, openssl_encrypt and mcrypt. No luck.
Any hint would be appreciated.
**Update: FIXED **
This PHP code is a perfect match for the CryptoJS code above.
function ssl_encrypt($pass, $data)
{
// Set a random salt
$salt = substr(md5(mt_rand(), true), 8);
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$pad = $block - (strlen($data) % $block);
$data = $data . str_repeat(chr($pad), $pad);
// Setup encryption parameters
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, "", MCRYPT_MODE_CBC, "");
$key_len = mcrypt_enc_get_key_size($td);
$iv_len = mcrypt_enc_get_iv_size($td);
$total_len = $key_len + $iv_len;
$salted = '';
$dx = '';
// Salt the key and iv
while (strlen($salted) < $total_len) {
$dx = md5($dx.$pass.$salt, true);
$salted .= $dx;
}
$key = substr($salted,0,$key_len);
$iv = substr($salted,$key_len,$iv_len);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $data);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
//return chunk_split(base64_encode('Salted__' . $salt . $encrypted_data),32,"\r\n");
return base64_encode('Salted__' . $salt . $encrypted_data);
}
function ssl_decrypt($password, $edata)
{
$data = base64_decode($edata);
print "Data: " . $data . "\n";
$salt = substr($data, 8, 8);
print "Salt (Base64): " . base64_encode($salt) . "\n";
$ct = substr($data, 16);
print "Content (Base64): " . base64_encode($ct) . "\n";
$rounds = 3;
$data00 = $password.$salt;
print "Data00 (Base64): " . base64_encode($data00) . "\n";
$md5_hash = array();
$md5_hash[0] = md5($data00, true);
$result = $md5_hash[0];
print "MD5-Hash[0] (Base64): " . base64_encode($result) . "\n";
for ($i = 1; $i < $rounds; $i++) {
$md5_hash[$i] = md5($md5_hash[$i - 1].$data00, true);
$result .= $md5_hash[$i];
print "Result (Base64): " . base64_encode($result) . "\n";
}
$key = substr($result, 0, 32);
print "Key (Base64): " . base64_encode($key) . "\n";
$iv = substr($result, 32, 16);
print "IV (Base64): " . base64_encode($iv) . "\n";
print "Decrypted: " . openssl_decrypt($ct, 'aes-256-cbc', $key, true, $iv) . "\n";
}
$encryptedString = ssl_encrypt('euhe68vjdr1aX4F091c7aCggSMBf0A7M', 'test');
$decryptedString = ssl_decrypt('euhe68vjdr1aX4F091c7aCggSMBf0A7M', $encryptedString);
I can't remember where I found it. Sorry.

This is a JavaScript thing, not a CryptoJS thing. Try this:
var decrypted = CryptoJS.AES.decrypt(encrypted, 'euhe68vjdr1aX4F091c7aCggSMBf0A7M', {iv: iv});
or this:
key = 'euhe68vjdr1aX4F091c7aCggSMBf0A7M';
var decrypted = CryptoJS.AES.decrypt(encrypted, key, {iv: iv});
You'll see that what you think is the key, isn't the key at all. It's being grouped with the optional parameters at the end, and lost.
'euhe68vjdr1aX4F091c7aCggSMBf0A7M' is your key, or is what your key is derived from.

Related

PHP decryption from JS breaks on longer values

When I'm trying to encrypt and decrypt a short word with several characters the following code does work. However if I try that with: gmdv4hwHN7SrHwEhX0Sb6dskWkVezAUlmjTvHOV6QSAySI8pOrOsPrQoYVQpWP7j It's like there's a max amount of characters. How do I resolve this issue?
JS
var CryptoJS = require("crypto-js")
var message = 'gmdv4hwHN7SrHwEhX0Sb6dskWkVezAUlmjTvHOV6QSAySI8pOrOsPrQoYVQpWP7j';
var key = '59b6ab45d379b89d794c87b74a511';
var iv = '0aaff094b6bc297a';
var encrypted = CryptoJS.AES.encrypt(
message,
CryptoJS.enc.Hex.parse(key),
{ iv: CryptoJS.enc.Hex.parse(iv) }
).toString()
Output: rQAT7R3TJUU+iLIzY+MNpoer7/br60oQrxo2O7BmI0b/O668bT7L5/cJUQbAFFDcwX4+8g3kjem6pCMGU7u9srVM7yauPmw8lcW9IiWSrbg=
PHP
<?php
$ciphertext = "rQAT7R3TJUU+iLIzY+MNpoer7/br60oQrxo2O7BmI0b/O668bT7L5/cJUQbAFFDcwX4+8g3kjem6pCMGU7u9srVM7yauPmw8lcW9IiWSrbg=";
$key = '59b6ab45d379b89d794c87b74a511';
$iv = '0aaff094b6bc297a';
var_dump (\openssl_decrypt(
base64_decode($ciphertext),
'aes-256-cbc',
$key,
OPENSSL_RAW_DATA,
$iv
));
Output: bool(false)

Decrypt Crypto-js encrypted text with key with PHP

I'm using Crypto-js for encrypting password with a key and send it to server. I want to decrypt it in server using PHP. How this can be done?
JS:
let encKey = "Secret Passphrase";
let text = "123";
let iv = CryptoJS.enc.Hex.parse("FgLFXEr1MZl2mEnk");
var encryptedText = CryptoJS.AES.encrypt(text, encKey, { iv: iv }).toString();
Encrypted text:
U2FsdGVkX1+EaW3J1GE1k/EU5h6C+nxBH364Xhez+b0=
PHP:
<?php
$strg = "U2FsdGVkX1+EaW3J1GE1k/EU5h6C+nxBH364Xhez+b0=";
$encryptedstrings = base64_decode($strg);
$encryptionMethod = 'aes-256-cbc';
$key = "Secret Passphrase";
$iv = "FgLFXEr1MZl2mEnk";
$rawText = openssl_decrypt($encryptedstrings, $encryptionMethod, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING , $iv);
var_dump($rawText);
Result:
string(32) "����>���s��ȡ�V?E��M���I"
I'm getting weird results here.
The following solution is not from my side but from #Artjom B., so all credits go to him. You will find the source here: https://stackoverflow.com/a/27678978/8166854.
To your problem: you run the CryptoJs encryption with a passphrase and not with a key. According to the docs (https://cryptojs.gitbook.io/docs/#the-cipher-algorithms) section cipher algorithms the (internal AES) key is derived from the passphrase with an outdated and unsecure function that should no longer be in use.
Artjom B. was able to make this key derivation available on PHP. As a side note: it is not necessary to present an
initialization vector (IV) to the encryption function as the IV is as well derived from the passphrase, so I'm leaving it
out in the following code.
This is the result on PHP-side:
solution for https://stackoverflow.com/questions/65234428/decrypt-crypto-js-encrypted-text-with-key-with-php
string(3) "123"
decryptedtext: 123
This is the code, please obey the warning:
This code is provided for achieve compatibility between different programming languages. It is not necessarily fully secure. Its security depends on the complexity and length of the password, because of only one iteration and the use of MD5. I would recommend to use at least a 20 character password with alphanumeric characters which is ideally randomly generated.
<?php
/*
source: https://stackoverflow.com/a/27678978/8166854 author: Artjom B.
Security notice: This code is provided for achieve compatibility between different programming languages.
It is not necessarily fully secure. Its security depends on the complexity and length of the password,
because of only one iteration and the use of MD5. I would recommend to use at least a 20 character password
with alphanumeric characters which is ideally randomly generated.
*/
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)
);
}
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;
}
echo 'solution for https://stackoverflow.com/questions/65234428/decrypt-crypto-js-encrypted-text-with-key-with-php' . PHP_EOL;
$key = "Secret Passphrase";
$strg = "U2FsdGVkX1+EaW3J1GE1k/EU5h6C+nxBH364Xhez+b0=";
$rawText = decrypt($strg, $key);
var_dump($rawText);
echo 'decryptedtext: ' . $rawText . PHP_EOL;
?>

Duplicate php openssl_encrypt in JavaScript

I'm trying to duplicate PHP string encryption using JavaScript. Here is the PHP code:
<?php
$iv = "1234567890123456";
$key = "aaaaaaaaaaaaaaaa";
$input = "texttexttexttext";
$encrypted = openssl_encrypt($input, "AES-256-CBC", $key, 0, $iv);
echo $encrypted;
// "ZwY1i+vqP3acszeDiscCTx/R4a6d2AtkcInmN9OTCNE="
However, when I try to duplicate it in JavaScript it gives a different ciphertext:
var aesjs = require("aes-js");
var base64 = require("js-base64");
var iv = aesjs.utils.utf8.toBytes("1234567890123456");
var key = aesjs.utils.utf8.toBytes("aaaaaaaaaaaaaaaa");
var text = aesjs.utils.utf8.toBytes("texttexttexttext");
var aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);
var encryptedBytes = aesCbc.encrypt(text);
var b64encoded = base64.Base64.encode(encryptedBytes);
console.log(b64encoded);
// "MTcyLDIsNjAsMTU5LDcxLDEwLDE4Myw4LDE…wyMTIsMjIyLDk3LDEyNCw1MywxNzIsMjIy"
I have no clue on how to make it give the same output. Any ideas?
Some things are going wrong:
First, the output from the JavaScript code is actually the base64 encoding of the string 172,2,60,159,71,10,183,8,1,…, not the encoding of the raw byte-buffer. I do not really know how to fix this idiomatically, but by using the aes.js hex-encoding utility function, we can convert it to base64:
var hex = aesjs.utils.hex.fromBytes(encryptedBytes);
var buf = Buffer.from(hex, 'hex');
console.log(buf.toString('base64'));
// rAI8n0cKtwiu1N5hfDWs3g==
The second problem is that in aes.js you are using AES128 encryption (aaaaaaaaaaaaaaaa is 128 bits long), but you are using AES256 encryption in the PHP code. We should update the PHP code (or the JS code):
$encrypted = openssl_encrypt($input, "AES-128-CBC", $key, 0, $iv);
echo $encrypted;
// rAI8n0cKtwiu1N5hfDWs3rPbz0UmvlbW+LJliYox03c=
We almost have the same output. But wait, the PHP output is twice as long. What happened?
Well, OpenSSL uses PKCS#7 padding. The Javascript code is unpadded however. To fix this, you should use PKCS#7 padding for the javascript text. For this you can just use the pkcs7 module. Another option is to use AES in counter (CTR) mode instead of CBC mode, if this is an option for you.
This is the PHP code that I have in the end:
<?php
$iv = "1234567890123456";
$key = "aaaaaaaaaaaaaaaa";
$input = "texttexttexttext";
$encrypted = openssl_encrypt($input, "AES-128-CBC", $key, 0, $iv);
echo $encrypted;
// output: 'rAI8n0cKtwiu1N5hfDWs3rPbz0UmvlbW+LJliYox03c='
And this is the JavaScript code:
var aesjs = require("aes-js");
var base64 = require("js-base64");
var pkcs7 = require("pkcs7");
var iv = aesjs.utils.utf8.toBytes("1234567890123456");
var key = aesjs.utils.utf8.toBytes("aaaaaaaaaaaaaaaa");
var text = aesjs.utils.utf8.toBytes("texttexttexttext");
var aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);
var encryptedBytes = aesCbc.encrypt(pkcs7.pad(text));
var hex = aesjs.utils.hex.fromBytes(encryptedBytes);
var buf = Buffer.from(hex, 'hex');
console.log(buf.toString('base64'));
// output: 'rAI8n0cKtwiu1N5hfDWs3rPbz0UmvlbW+LJliYox03c='
PS I personally prefer using CTR mode, because PKCS#7 implementations sometimes expose padding oracles which break the encryption. (I checked the mentioned pkcs#7 library which should be good, but please don't try to implement this yourself.)

AES 256 on the client side (JS) and in the server (PHP)

I'm trying to encrypt and decrypt data on the server side and the client using the same type of operation, which is AES-256.
On the server I use PHP and client I use CryptoJS so far I could only encrypt and decrypt the client on the server, see the code:
JS
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/pbkdf2.js"></script>
<script>
var salt = CryptoJS.lib.WordArray.random(128/8);
var key256Bits500Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 256/32, iterations: 500 });
var iv = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');
var encrypted = CryptoJS.AES.encrypt("Message", key256Bits500Iterations, { 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);
</script>
PHP
<?php
$encrypted = base64_decode("data_base64"); // data_base64 from JS
$iv = base64_decode("iv_base64"); // iv_base64 from JS
$key = base64_decode("key_base64"); // key_base64 from JS
$plaintext = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv ), "\t\0 " );
How can I encrypt and decrypt data on both sides (client and server) so that communicate in the same language using PHP and CryptoJS?
Your code looks fine apart from a padding mismatch. CryptoJS uses PKCS#5/PKCS#7 padding by default whereas MCrypt only supports ZeroPadding.
If you're only sending textual plaintexts, then you can safely use
CryptoJS.AES.encrypt("Message", key, { iv: iv, padding: CryptoJS.pad.ZeroPadding });
If not, then you should use proper pkcs7unpad in PHP:
$plaintext = pkcs7unpad( mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv ), 16 );
Other problems with your code are that you directly use CryptoJS.AES.encrypt(...).toString(). This will create an OpenSSL formatted string which is not purely the ciphertext. You need to use
CryptoJS.AES.encrypt(...).ciphertext.toString(CryptoJS.enc.Base64);
to also be sure about the encoding.
Right now, this is only obfuscation, since you're sending the key along with the ciphertext. I suspect that you want to derive the key in PHP too. If yes, then you will only need to send the random salt along with the ciphertext under the assumption that the server knows the password.
PHP provides a PBKDF2 implementation from version 5.5 onwards.
Full JavaScript part without PBKDF2 involvement:
var message = 'My string - Could also be an JS array/object';
var iv = 'a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8';
var key = 'c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8'; // 256-bit hex encoded
var keyBytes = CryptoJS.enc.Hex.parse(key);
var ivBytes = CryptoJS.enc.Hex.parse(iv);
var encrypt = CryptoJS.AES.encrypt(message, keyBytes, {
iv: ivBytes,
padding: CryptoJS.pad.ZeroPadding
}).ciphertext.toString(CryptoJS.enc.Base64);
produces:
j86KHBVRsDGKUnOiYdkEotsFL/lY/1tzz/h3Ay+vlEX11fC055m7vaF6q7w13eUj
Full PHP part without PBKDF2 involvement:
<?php
$iv = 'a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8';
$key = 'c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8';
$ct = 'j86KHBVRsDGKUnOiYdkEotsFL/lY/1tzz/h3Ay+vlEX11fC055m7vaF6q7w13eUj';
$ivBytes = hex2bin($iv);
$keyBytes = hex2bin($key);
$ctBytes = base64_decode($ct);
$decrypt = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $keyBytes, $ctBytes, MCRYPT_MODE_CBC, $ivBytes));
echo $decrypt;
produces:
My string - Could also be an JS array/object
The same is possible with the OpenSSL extension:
<?php
$iv = 'a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8';
$key = 'c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8';
$ct = 'j86KHBVRsDGKUnOiYdkEotsFL/lY/1tzz/h3Ay+vlEX11fC055m7vaF6q7w13eUj';
$ivBytes = hex2bin($iv);
$keyBytes = hex2bin($key);
$ctBytes = base64_decode($ct);
$decrypt = openssl_decrypt($ctBytes, "aes-256-cbc", $keyBytes, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $ivBytes);
echo($decrypt);

php mcrypt to javascript aes integration

I am trying to use javascript to encode data with AES-256-CBC and php mcrypt libraries to decode, and vise versa.
I am aware of the problematic nature of javascript and the fact that anyone sees the key, but I am using javascript a scripting tool for non-web environment - so not worried about it.
I found pidder https://sourceforge.net/projects/pidcrypt/
and encrypted some data with the demo page, then tried to decrypt it via php, but something is wrong and I can't seem to find what... I am using the same key with both ends, a 32 byte string
any pointers will be appreciated
~~~
$encrypted = "string after pidder encryption";
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_256,'',MCRYPT_MODE_CBC,'');
$iv_size = mcrypt_enc_get_iv_size($cipher);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
mcrypt_generic_init($cipher, $key, $iv);
$encrypted = base64_decode($encrypted);
echo "after b64decode: " . $encrypted . "\n\n\n";
$encrypted = mdecrypt_generic($cipher, $encrypted);
echo "decrypt:" . $encrypted;
~~~
Try MCRYPT_RIJNDAEL_128 with a 32-byte key for AES-256.
AES is a 128-bit block cipher that supports 128-, 192-, and 256-bit keys. Rijndael-256 is a 256-bit block cipher and AES. AES is a 128-bit block specification for Rijndael.
Pidder uses key derivation function to get the key from password (it should be HMAC-SHA1, i guess), but you seems to use plain password as a key.
Javascript Mcrypt plays well with PHP mcrypt. You could use that instead of pidder.
Your code is sequential, honestly, I dont tried to fix, but I have a function that work well and can help you.
/**
* Encrypt Token
*
* #param unknown $text
*/
private function rijndaelEncrypt($text) {
$iv_size = mcrypt_get_iv_size ( MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB );
$iv = mcrypt_create_iv ( $iv_size, MCRYPT_RAND );
$key = 'your key';
return base64_encode ( mcrypt_encrypt ( MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv ) );
}
/**
* Decrypt
*
* #param unknown $text
*/
private function rijndaelDecrypt($text) {
$iv_size = mcrypt_get_iv_size ( MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB );
$iv = mcrypt_create_iv ( $iv_size, MCRYPT_RAND );
$key = 'your key';
// I used trim to remove trailing spaces
return trim ( mcrypt_decrypt ( MCRYPT_RIJNDAEL_256, $key, base64_decode ( $text ), MCRYPT_MODE_ECB, $iv ) );
}
See http://us3.php.net/manual/en/function.mcrypt-encrypt.php
first of all: MCRYPT_RIJNDAEL_256 is NOT(!) AES-256-CBC, if you want this encryption you have to use MCRYPT_RIJNDAEL_128 with an 265bit aka 32 character key.
This would be the php part:
function decrypt($data, $key) {
if(32 !== strlen($key)) $key= hash('SHA256', $key, true);
$data = base64_decode($data);
$data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
$padding = ord($data[strlen($data) - 1]);
return substr($data, 0, -$padding);
}
This php function includes padding which is an important part, because if the suplied data lenght is not a multiple of the key, you will get something odd.
For decoding we use some of my Node.js scripts with an emulated method of php's str_repeat for the iv:
var crypto = require('crypto');
function encrypt(data, key) {
key = key || new Buffer(Core.config.crypto.cryptokey, 'binary'),
cipher = crypto.createCipheriv('aes-256-cbc', key.toString('binary'), str_repeat('\0', 16));
cipher.update(data.toString(), 'utf8', 'base64');
return cipher.final('base64');
}
function str_repeat(input, multiplier) {
var y = '';
while (true) {
if (multiplier & 1) {
y += input;
}
multiplier >>= 1;
if (multiplier) {
input += input;
} else {
break;
}
}
return y;
}
NOTE: It is not recommend to use a static IV (Initialization vector)!
NOTE: JavaScript part is for Node.js using it's crypto library.
I hope this works for you.

Categories

Resources