在节点.js中重新创建MCRYPT_RIJNDAEL_128


Recreating MCRYPT_RIJNDAEL_128 in node.js

尝试在node.js中重新创建以下php加密代码:

$size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($size, MCRYPT_RAND);
$msg = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, 'MY_KEY_LONG_STRING', 'PLAINTEXT', MCRYPT_MODE_ECB, $iv));

试过这个:

var text = 'PLAINTEXT';
var len = text.length;
for (var i = 0; i < 16 - len % 16; i++) {  // pad to multiple of block size 
    text += ''0';
}
var key = 'MY_KEY_LONG_STRING';
key = key.substr(0, 16); // trim to expected key size for aes128
var cipher = crypto.createCipher('aes-128-ecb', key);
cipher.setAutoPadding(false); // did our own padding, to match mcrypt_encrypt
var encrypted = cipher.update(text, 'utf8', 'base64');
encrypted += cipher.final('base64');

得到与 php 不同的结果...

还尝试使用 IV 创建密码(甚至不应该在 aes-128-ecb 中使用):

var cipher = crypto.createCipheriv('aes-128-ecb', key, '');

此外,与 php 的结果不同。任何想法如何使它的行为与php版本完全相同?

玩两个结构相当糟糕的库可能会很有趣。我不会做所有的工作,而是会根据要求为您提供想法:

    PHP 不是删除密钥字节,
  • 而是使用零填充将它们扩展到下一个可用的密钥大小 - 在您的情况下为 192 位或 24 字节;为此,您需要指定 aes-192-ecb as 算法(您需要继续使用 MCRYPT_RIJNDAEL_128 但替换,PHP 中的 128 是块大小而不是密钥大小)
  • 填充不正确,PHP 填充 0..15 零字节而不是 1..16 字节
  • 您不能使用 2 参数createCipher因为第二个参数是密码;node.js 如果您使用该参数,则执行密钥派生,因此您需要改用 3 参数createCipher并提供任何 16 字节的 IV

PHP 中的 IV 代码只对随机数生成器不必要地征税,不使用 IV


执行填充的代码

var padSize = 16 - ((len + 16 - 1) % 16 + 1);
for (var i = 0; i < padSize; i++) {  // pad 0 .. 15 until to multiple of block size 
    text += ''0';
}

或者您可以使用自己的填充方法(在问题中),除非len % 16 == 0.

这是我的代码

来解决从PHP迁移到NodeJS的问题。我有严格的 32 字节密钥,所以我必须使用 aes-256-ecb .

我想重写的PHP代码:

$text = "Some super mega text I want to encode";
$skey = "rcbTw667C7zxghZ5U3gwhQlp22t8c5Rq";
function encode($text,$skey) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $skey, $text, MCRYPT_MODE_ECB, $iv);
    return base64_encode($crypttext);
}
echo encode($text,$skey);

输出:

dU1eOy+YwkYvm/KCTB8aqR1UsisyrHrvBu+E/H3G/s0aagMDKlNFekGXNQyFMFJD

节点JS:

var crypto = require('crypto');
var text = "Some super mega text I want encode";
var skey = "rcbTw667C7zxghZ5U3gwhQlp22t8c5Rq";
function encode(text, skey) {
    var len = text.length;
    var padSize = 16 - ((len + 16 - 1) % 16 + 1);
    for (var i = 0; i < padSize; i++) { 
        text += ''0';
    }
    var cipher = crypto.createCipheriv('aes-256-ecb', skey, '');
    cipher.setAutoPadding(false);
    var encrypted = cipher.update(text, 'utf8', 'base64');
    encrypted += cipher.final('base64');
    return encrypted;
}
console.log(encode(text, skey));

输出:

dU1eOy+YwkYvm/KCTB8aqR1UsisyrHrvBu+E/H3G/s0aagMDKlNFekGXNQyFMFJD

NodeJS mcrypt 包也可以工作:

npm install mcrypt

法典:

var text = "Some super mega text I want encode";
var skey = "rcbTw667C7zxghZ5U3gwhQlp22t8c5Rq";
function encode(text, skey) {
    var MCrypt = require('mcrypt').MCrypt;
    var rijEcb = new MCrypt('rijndael-128', 'ecb');
    rijEcb.open(skey);
    var ciphertext = rijEcb.encrypt(text);
    return ciphertext.toString('base64');
}
console.log(encode(text, skey));

输出:

dU1eOy+YwkYvm/KCTB8aqR1UsisyrHrvBu+E/H3G/s0aagMDKlNFekGXNQyFMFJD

我尝试了其他选项,但没有任何效果,但这对我有用。

function encrypt(text) {
  text = '' + text;
  var crypto = require('crypto');
  var len = text.length;
  var padSize = 16 - (((len + 16 - 1) % 16) + 1);
  var data = String.fromCharCode(padSize);
  var text = text + data.repeat(padSize);
  var cipher = crypto.createCipheriv('aes-128-ecb','secretKey', '');
  cipher.setAutoPadding(false);
  var encrypted = cipher.update(text, 'utf8', 'base64');
  encrypted += cipher.final('base64');
  return encrypted;
}

PHP 中的类似物

function aes128Encrypt($str,$key){
$block = mcrypt_get_block_size('rijndael_128', 'ecb');
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB));
}