Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Encrypt in nodejs and decrypt in php or vice versa
var crypto = require('crypto');
var key = 'MySecretKey12345';
var iv = '1234567890123456';
var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
var text = 'plain text';
var encrypted = cipher.update(text, 'utf8', 'binary');
encrypted += cipher.final('binary');
hexVal = new Buffer(encrypted, 'binary');
newEncrypted = hexVal.toString('hex');
console.log('Encrypted: ', newEncrypted);
var decrypted = decipher.update(newEncrypted, 'hex', 'binary');
decrypted += decipher.final('binary');
console.log('Decrypted: ', decrypted);
<?php
class Crypto
{
private $encryptKey = 'MySecretKey12345';
private $iv = '1234567890123456';
private $blocksize = 16;
public function decrypt($data)
{
return $this->unpad(mcrypt_decrypt(MCRYPT_RIJNDAEL_128,
$this->encryptKey,
hex2bin($data),
MCRYPT_MODE_CBC, $this->iv), $this->blocksize);
}
public function encrypt($data)
{
//don't use default php padding which is '\0'
$pad = $this->blocksize - (strlen($data) % $this->blocksize);
$data = $data . str_repeat(chr($pad), $pad);
return bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,
$this->encryptKey,
$data, MCRYPT_MODE_CBC, $this->iv));
}
private function unpad($str, $blocksize)
{
$len = mb_strlen($str);
$pad = ord( $str[$len - 1] );
if ($pad && $pad < $blocksize) {
$pm = preg_match('/' . chr($pad) . '{' . $pad . '}$/', $str);
if( $pm ) {
return mb_substr($str, 0, $len - $pad);
}
}
return $str;
}
}
$crypto = new Crypto();
$text = 'plain text';
$encrypted = $crypto->encrypt($text);
//$encrypted = '9eb6c9052d1de4474fb52d829360d5af';
echo "Encrypted: ".$encrypted."\n";
$decrypted = $crypto->decrypt($encrypted);
echo "Decrypted: $decrypted\n";
@mightydes

This comment has been minimized.

Copy link

@mightydes mightydes commented Jul 21, 2014

In encrypt you use strlen to evaluate $pad:

$pad = $this->blocksize - (strlen($data) % $this->blocksize);

But, in unpad you use mb_strlen and mb_substr, it's a mistake.
Also, you shoul use <=, rather then < in condition if ($pad && $pad < $blocksize).

Here is modified version of unpad method:

    private function unpad($str, $blocksize)
    {
        $len = strlen($str);
        $pad = ord($str[$len - 1]);
        if ($pad && $pad <= $blocksize) {
            if (substr($str, -$pad) === str_repeat(chr($pad), $pad)) {
                return substr($str, 0, $len - $pad);
            }
        }
        return $str;
    }
@achimkoellner

This comment has been minimized.

Copy link

@achimkoellner achimkoellner commented Dec 15, 2015

Dear Rojan, thanks for that fantastic script.
I'm afraid the JS script does not work with utf-8 strings such as "ÖÄÜßöäü".
They might be encoded properly (not sure) but when decoded they end up something like this "����ö"
I gave a try encoding it using the node.js uft8 lib but that failed.
I removed the 'utf8' argument from line #8 that worked for the string "ÖÄÜßöäü" but e.g. not for a more complex JSON-String like that
'{"name":"ÖÄÜßöäü", ort:"pöäsd asdölkj sadfj asdflkj"}'

it gave me this error on the console:

crypto.js:202
  var ret = this._handle.final();
                         ^
Error: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
    at Error (native)
    at Decipheriv.Cipher.final (crypto.js:202:26)
    at Object.<anonymous> (/myapp/test.js:15:23)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3

EDIT: I changed the "binary" arguments for decryption to "utf8" and it worked well with special characters.

var crypto = require('crypto');
var key = 'MySecretKey12345';
var iv = '1234567890123456';
var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
//decipher.setAutoPadding(false);

var text = '{"name":"ÖÄÜßöäü", ort:"pöäsd asdölkj sadfj asdflkj"}';
var encrypted = cipher.update(text, 'utf8', 'binary');
encrypted += cipher.final('binary');
hexVal = new Buffer(encrypted, 'binary');
newEncrypted = hexVal.toString('hex');
console.log('Encrypted: ', newEncrypted);

var decrypted = decipher.update(newEncrypted, 'hex', 'utf-8');
decrypted += decipher.final('utf-8');

console.log('Decrypted: ', decrypted);
@vip3r011

This comment has been minimized.

Copy link

@vip3r011 vip3r011 commented May 17, 2018

WOn't work in php 7.2, since mcrypt was removed

@bato3

This comment has been minimized.

Copy link

@bato3 bato3 commented Jul 3, 2018

@vip3r011use any php library/example for aes-128-cbc method, eg: https://gist.github.com/odan/138dbd41a0c5ef43cbf529b03d814d7c

@vishnusadanandan

This comment has been minimized.

Copy link

@vishnusadanandan vishnusadanandan commented Jul 29, 2019

Is this works fine with public key private key encrypt decrypt

@Lawlez

This comment has been minimized.

Copy link

@Lawlez Lawlez commented Oct 28, 2020

I created an updated Gist for use in Web(browsers), Node.JS, command line and PHP 7
https://gist.github.com/Lawlez/88e04e3541cc0608c953a118b86bfc1a

I'm still working on a solution that allows me to use any implementation (Node / PHP / openssl) for encryption and get the web version to decrypt it successfully. currently, I'm still facing issues when trying to decrypt a string in node or web that was encrypted using openssl CLI.

hope it helps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment