Reputation: 2019
I have a PHP code that encrypt in AES-128 an ip address:
$ip = "MY_IP";
$secret = "MY_KEY";
$ip = @mcrypt_ecb(MCRYPT_RIJNDAEL_128, $secret, $ip, MCRYPT_ENCRYPT);
$encrypted = bin2hex($ip); // encrypted: 2854edb405cb7230ba1f4b87acddba8a
What I need to do is to have the same piece of code but using javascript/node.js. I've searched in the crypto node.js native module but I wasn't able to reproduce the same result:
var crypto = require('crypto');
var ip = "MY_IP";
var secret = "MY_KEY";
var cipher = crypto.createCipher("AES-128-ECB", secret);
var encrypted = cipher.update(ip, 'utf8', 'hex');
encrypted += cipher.final('hex'); // encrypted: e84c06888696edda0139e98fc2c0a8cc
Does someone have an idea ?
Upvotes: 4
Views: 1630
Reputation: 106696
The problem here is that there are some things that PHP's mcrypt extension (and node's createCipher()
) does behind the scenes that you're probably not aware of.
First off, createCipher()
accepts a 'password' that is hashed with MD5 to derive the actual key. So instead what you should be using is createCipheriv()
, which allows you to pass the key (and IV) directly, like PHP's mcrypt accepts. In ECB mode, IVs are ignored, so you can just pass in an empty string for the IV parameter.
Secondly, PHP's mcrypt will magically pad both your input and your key with null bytes if they are less than the cipher's block size and key size, respectively.
So for AES-128-ECB, we need to make sure the input and key lengths are a multiple of 16 bytes. With all of this knowledge we then find that appropriate code for the built-in crypto
module might look something like:
var crypto = require('crypto');
function makePadded(str) {
var buf;
var len = str.length;
if (str.length % 16)
len = str.length + (16 - str.length % 16);
buf = new Buffer(len);
buf.fill(0);
buf.write(str, 0, str.length);
return buf;
}
var ip = makePadded('MY_IP');
var secret = makePadded('MY_KEY');
var cipher = crypto.createCipheriv("AES-128-ECB", secret, '');
var encrypted = cipher.update(ip, 'binary', 'hex');
encrypted += cipher.final('hex');
// Slice off at 16 bytes to match the input length
encrypted = encrypted.slice(0, 32);
console.log(encrypted);
One last thing that might be worth mentioning is that MCRYPT_RIJNDAEL_128
in PHP can be used to do 128, 192, or 256 bit encryption. So in PHP if 0 < keylen <= 16
then 128-bit encryption will be used, 192-bit encryption will be used if 16 < keylen <= 24
and 256-bit encryption will be used if 24 < keylen <= 32
. However in node, you will need to adjust the cipher name appropriately, as node does not do the kind of "automatic adjustment" that PHP does.
Upvotes: 3
Reputation: 2019
I've posted too quickly, found the solution:
$> npm install mcrypt
And then the code:
var MCrypt = require('mcrypt').MCrypt;
var ip = "MY_IP";
var secret = "MY_KEY"
var desEcb = new MCrypt('rijndael-128', 'ecb');
desEcb.open(secret);
var cipherText = desEcb.encrypt(ip); // cipherText: 2854edb405cb7230ba1f4b87acddba8a
MCrypt github for more encryption tool: https://github.com/tugrul/node-mcrypt
Upvotes: 3
Reputation: 1
in nodejs - password must be a 'binary' encoded string or a buffer. in PHP, the deprecated @mcrypt_ecb expects a key to be a string
Upvotes: 0