In node.js, I use the build in function to encrypt data like that:
var text = "Yes";
var password = "123456";
var encrypt = crypto.createCipher('aes-256-cbc', password);
var encryptOutput1 = encrypt.update(text, 'base64', 'base64');
var encryptOutput2 = encrypt.final('base64');
var encryptedText = encryptOutput1 + encryptOutput2;
the output (encrypted text) is: OnNINwXf6U8XmlgKJj48iA==
Then I use decrypt it in PHP:
$encrypted = 'OnNINwXf6U8XmlgKJj48iA==';
(or $encrypted = base64_decode('OnNINwXf6U8XmlgKJj48iA==') );
$dtext2 = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CBC);
echo "Decrypted: $dtext2";
I will get some funny characters, which I can't decrypted it. I tried with/without base64_decode or MCRYPT_RIJNDAEL_128.. all fail.
Then I check how the encryption in PHP, it looks very different from the output from node.js.
$text = "Yes";
$key = "123456";
$eText = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC);
echo "Encrypted: $eText \n";
echo "base64: " . base64_encode($eText) . " \n";
$dtext1 = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $eText, MCRYPT_MODE_CBC);
echo "Decrypted: $dtext1 \n\n";
It can encrypt and decrypt. and the encrypted data is : njCE/fk3pLD1/JfiQuyVa6w5H+Qb/utBIT3m7LAcetM=
which is very different from the output from node.js please advise how I can encrypt and decrypt between node.js & php. thanks. :)
@Mel here is what I have in PHP:
$text = "Yes";
$key = "32BytesLongKey560123456789ABCDEF";
$iv = "sixteenbyteslong";
/* Open the cipher */
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
/* Intialize encryption */
mcrypt_generic_init($td, $key, $iv);
/* Encrypt data */
$eText = mcrypt_generic($td, $text);
echo "Encrypted Data: $eText \n";
echo "base64: " . base64_encode($eText) . " \n";
/* Terminate encryption handler */
mcrypt_generic_deinit($td);
/* Initialize encryption module for decryption */
mcrypt_generic_init($td, $key, $iv);
/* Decrypt encrypted string */
$dText = mdecrypt_generic($td, $eText);
/* Terminate decryption handle and close module */
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
/* Show string */
echo trim($dText) . "\n";
However, it still doesn't work.
The encrypted base 64 in PHP is: 80022AGM4/4qQtiGU5oJDQ== The encrypted base 64 in nodejs is: EoYRm5SCK7EPe847CwkffQ==
thus, i can't decrypt the nodejs one in PHP.
I wonder if it is because nodejs doesn't require $iv?
In PHP, Encryption and Decryption of a string is possible using one of the Cryptography Extensions called OpenSSL function for encrypt and decrypt. openssl_encrypt() Function: The openssl_encrypt() function is used to encrypt the data. Parameters: $data: It holds the string or data which need to be encrypted.
Using Clean architecture for Node.NodeJS provides inbuilt library crypto to encrypt and decrypt data in NodeJS. We can use this library to encrypt data of any type. You can do the cryptographic operations on a string, buffer, and even a stream of data. The crypto also holds multiple crypto algorithms for encryption.
I have another working example in this other post if it helps for anyone else.
If you make sure you use an 32 characters length "key/secret" and a 16 characters length IV in both PHP and Node, and base64
encryption encoding and utf8
message encoding in Node, then you should not have any issues with any differences in the padding schema.
Regards, Ignacio
Seven months late, but I was struggling with this as well, and found a solution. Apparently, PHP pads the input with zero bytes to make its size a multiple of the block size. For example, using AES-128, the 14 byte input "contrabassists" will be padded with two zero bytes, like this:
"contrabassists\0\0"
A N*blocksize byte input is left alone.
The standard Node crypto functions, however, use a different padding scheme called PKCS5. PKCS5 doesn't add zeros, but adds the length of the padding, so again using AES-128, "contrabassists" would become:
"contrabassists\2\2"
Even a N*blocksize byte input gets padded in PKCS5. Otherwise, it's impossible to remove the padding after decoding. The input "spectroheliogram" would then become:
"spectroheliogram\16\16\16\16\16\16\16\16\16\16\16\16\16\16\16\16"
To make PHP m_crypt encryption compatible with Node decryption, you'll have to pad the input yourself:
$pad = $blocksize - (strlen($input) % $blocksize);
$input = $input . str_repeat(chr($pad), $pad);
The other way around, you'll have to read the last byte of the decoded data and cut off the padding yourself.
Example functions: (added 01-14-2012)
In PHP, this function would return AES-128 encrypted, hex encoded data that can be decrypted by Node:
function nodeEncrypt($data, $key, $iv) {
$blocksize = 16; // AES-128
$pad = $blocksize - (strlen($data) % $blocksize);
$data = $data . str_repeat(chr($pad), $pad);
return bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv));
}
In Node, the following would decrypt the data:
function nodeDecrypt(data, key, iv) {
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
var chunks = []
chunks.push(decipher.update(data.toString(),'hex','binary'))
chunks.push(decipher.final('binary'))
return chunks.join('')
}
I haven't done the reverse yet, but it should be straightforward once you understand the padding scheme. I haven't made any assumptions about key/iv generation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With