At first, Node.js crypto.
// Both of key and IV are hex-string, but I hide them in Stackoverflow.
var secretKey = new Buffer('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'hex'), // 48 chars
iv = new Buffer('bbbbbbbbbbbbbbbb', 'hex'); // 16 chars
var str = 'This string will be encrypted.';
var cipher = crypto.createCipheriv('des-ede3-cbc', secretKey, iv),
cryptedStr = cipher.update(str, 'utf8', 'base64') + cipher.final('base64');
Then, PHP mcrypt.
$key = pack('H*', "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
$iv = pack('H*', "bbbbbbbbbbbbbbbb");
$string = 'This string will be encrypted.';
$text = mcrypt_encrypt(MCRYPT_3DES, $key, $string, MCRYPT_MODE_CBC, $iv);
$text_base64 = base64_encode($text);
Problem.
In the same string, same algorithm and same encoding.
Still there is a little part not match that is cipher.final()
.
Below is the real sample output.
// Node.js output.
UKBI17EIHKNM2EU48ygsjil5r58Eo1csByAIFp9GhUw=
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Same part
// PHP output.
UKBI17EIHKNM2EU48ygsjil5r58Eo1csAY4C0JZoyco=
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Same part
Why cipher.final()
make results different?
How could make the same results in Node.js on condition that don't modify PHP code.
Since you can't change your PHP code, you will need to modify the node.js code.
The problem is that node.js' crypto module uses only PKCS#7 padding, whereas PHP uses only zero padding. You can however disable padding in node.js (
setAutoPadding(false)
) to implement your own zero padding:And use it like this:
Output:
Here is an implementation of a matching unpad function: