我有一个用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参数传入一个空字符串。
所以对于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期望键是字符串