Node.js/javascript加密AES-128像mcrypt_ecb在PHP


Node.js/javascript encrypt AES-128 like mcrypt_ecb in PHP

我有一个用AES-128加密ip地址的PHP代码:

$ip = "MY_IP";
$secret = "MY_KEY";
$ip = @mcrypt_ecb(MCRYPT_RIJNDAEL_128, $secret, $ip, MCRYPT_ENCRYPT); 
$encrypted = bin2hex($ip);  // encrypted: 2854edb405cb7230ba1f4b87acddba8a

我需要做的是有相同的一块代码,但使用javascript/node.js。我在crypto node.js原生模块中搜索过,但我无法复制相同的结果:

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

谁有什么主意?

我发得太快了,找到了解决办法:

$> npm install mcrypt

然后是代码:

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获取更多加密工具:https://github.com/tugrul/node-mcrypt

这里的问题是PHP的mcrypt扩展(和节点的createCipher())在幕后做了一些您可能没有意识到的事情。

首先,createCipher()接受一个'密码',该密码与MD5散列以派生出实际的密钥。因此,您应该使用的是createCipheriv(),它允许您直接传递密钥(和IV),就像PHP的mcrypt接受一样。在ECB模式下,IV将被忽略,因此您可以为IV参数传入一个空字符串。

其次,PHP的mcrypt将神奇地将 您的输入您的密钥填充为空字节,如果它们分别小于密码的块大小和密钥大小。

所以对于AES-128-ECB,我们需要确保输入和密钥长度是16字节的倍数。有了所有这些知识,我们发现内置crypto模块的适当代码可能类似于:

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);

最后一件可能值得一提的事情是,PHP中的MCRYPT_RIJNDAEL_128可以用于128、192或256位加密。因此,在PHP中,如果0 < keylen <= 16则使用128位加密,如果16 < keylen <= 24将使用192位加密,如果24 < keylen <= 32将使用256位加密。但是在node中,您需要适当地调整密码名,因为node不做PHP所做的那种"自动调整"。

在nodejs - password必须是一个'二进制'编码字符串或缓冲区。在PHP中,已弃用的@mcrypt_ecb期望键是字符串