4

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 ?

3
  • 1
    Stop using @ to hide errors. It masks issues. Commented Jul 17, 2015 at 16:26
  • What is the connection? Moreover this php code is not mine, so your comment does not help. Commented Jul 17, 2015 at 20:45
  • The connection is that it's bad practice that will make bugs happen that are hard to track down. If you do any PHP work, avoid the @ operator in virtually all cases. Commented Jul 17, 2015 at 20:53

3 Answers 3

3

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

Sign up to request clarification or add additional context in comments.

Comments

3

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.

4 Comments

Well, I've learn many thing with your answer. Meanwhile I got an error on var cipher = crypto.createCipheriv("AES-128-ECB", secret, ''); ==> crypto.js:346 this._binding.initiv(cipher, toBuf(key), toBuf(iv)); Error: error:0607A082:digital envelope routines:EVP_CIPHER_CTX_set_key_length:invalid key length
What is the size of your key? Also is it hex encoded already?
It is 32 and encoded in utf-8. Moreover, what solution do you find the best between yours and the use of the mcrypt package that I've found on npm ?
If your key size is 32 bytes long, then you should be using AES-256-ECB instead. You'll also need to change the 16 to 32 in makePadded and slice(0, 32) to slice(0, 64).
0

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

1 Comment

Maybe passing the password in binary will work but I prefer to use the package I found, it doesn't use native crypto module that is unstable

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.