【问题标题】:How to decrypt a message in node.js that was encrypted with Rijndael-256?如何解密使用 Rijndael-256 加密的 node.js 中的消息?
【发布时间】:2015-12-18 13:12:23
【问题描述】:

我有一条消息在存储到 MySQL 数据库之前使用 PHP 加密。

我需要能够使用 node.js/javascript 解密此消息。

在研究如何做到这一点时,我遇到了crypto 模块。我尝试使用它,但我遇到了以下错误

C:\Program Files\nodejs\node_modules\mysql\lib\protocol\Parser.js:82
        throw err;
              ^
TypeError: Not a buffer
    at TypeError (native)
    at new Decipheriv (crypto.js:282:16)
    at Object.Decipheriv (crypto.js:279:12)
    at Query.<anonymous> (C:\Program Files\nodejs\modules\validator.js:76:27)
    at Query._callback (C:\Program Files\nodejs\modules\dbconnect.js:46:14)
    at Query.Sequence.end (C:\Program Files\nodejs\node_modules\mysql\lib\protoc
ol\sequences\Sequence.js:96:24)
    at Query._handleFinalResultPacket (C:\Program Files\nodejs\node_modules\mysq
l\lib\protocol\sequences\Query.js:144:8)
    at Query.EofPacket (C:\Program Files\nodejs\node_modules\mysql\lib\protocol\
sequences\Query.js:128:8)
    at Protocol._parsePacket (C:\Program Files\nodejs\node_modules\mysql\lib\pro
tocol\Protocol.js:274:23)
    at Parser.write (C:\Program Files\nodejs\node_modules\mysql\lib\protocol\Par
ser.js:77:12)

这就是我尝试使用加密模块解密消息的方式

var crypto = require('crypto');
var encryptedText = new Buffer(rows[0]['password'], 'base64');
var decipher = crypto.createDecipheriv('sha256', 'The encryption password', 32);
var decrypted = decipher.update(encryptedText, 'hex', 'utf8') + decipher.final('utf8');

console.log('My Pass: ' + decrypted);

这就是我使用 PHP 加密消息的方式

define('PHP_HASH_ALGORITHIM','sha256');
define('PHP_MCRYPT_CIPHERNAME','rijndael-256');
define('PHP_MCRYPT_MODE','ecb');
define('PHP_MCRYPT_KEY','The encryption password');

function encrypt($input, $textkey = PHP_MCRYPT_KEY) {
    $securekey = hash(PHP_HASH_ALGORITHIM, $textkey, TRUE);
    $iv = mcrypt_create_iv(32);
    return base64_encode(mcrypt_encrypt(PHP_MCRYPT_CIPHERNAME, $securekey, $input, PHP_MCRYPT_MODE, $iv));
}

这就是我使用 PHP 解密消息的方式

function decrypt($input, $textkey = PHP_MCRYPT_KEY) {
    $securekey = hash(PHP_HASH_ALGORITHIM, $textkey, TRUE);
    $iv = mcrypt_create_iv(32);
    return trim(mcrypt_decrypt(PHP_MCRYPT_CIPHERNAME, $securekey, base64_decode($input), PHP_MCRYPT_MODE, $iv));
}

如何使用加密正确解密消息?

【问题讨论】:

  • @BurninLeo 我在哪里可以找到 crypto.js 文件?
  • 当我将 iv 值从 32 更改为此 var iv = new Buffer(32, 'binary'); 我收到此错误 Error: Unknown cipher 我不确定是否应该将数字 32 传递到那里
  • 对不起,我看错了错误信息。根据nodejs.org/api/…,“key 和 iv 必须是‘二进制’编码的字符串或缓冲区。” - 即,在我看来,32 根本无效。

标签: javascript php node.js encryption rijndael


【解决方案1】:

在 PHP 中,您使用的 Rijndael 具有 256 位的块大小(“rijndael-256”)和 256 位的密钥大小(通过 SHA-256 输出确定)。 Rijndael 还支持 128 和 192 位的块大小。 Node.js 的加密模块仅支持与 Rijndael 相同的 AES,具有 128 位的固定块大小和可变密钥大小(128、192 或 256 位)。这意味着您无法使用 Node.js 的加密模块重新创建相同的功能。

您需要找到支持 Rijndael-256 的模块。 mcryptnode-rijndael 浮现在脑海中,它们都是 libmcrypt 的简单包装器,您需要另外安装。

如果您可以将 PHP 代码更改为使用 AES (rijndael-128),这可能会更容易。

请记住,SHA-256 是一种散列函数,而不是一种加密算法。您需要使用crypto.createHash(algorithm) 而不是crypto.createDecipheriv() 从密码中派生密钥。


安全注意事项:

  • 当您派生密钥时,您应该使用随机盐和多次迭代来执行此操作。为此使用 PBKDF2、bcrypt 或 scrypt。如果密码很短(少于 20 个字符),那么很容易被暴力破解。

  • 不要使用 MCrypt。是弃用。 PHP 和 Node.js 都支持 OpenSSL 加密,这样可以更轻松地找到兼容的密码。 (还是需要选择和padding一样的操作模式。)

  • 不要使用 ECB 模式。它在语义上不安全。至少使用带有随机初始化向量 (IV) 的 CBC 模式。 IV 不必保密,因此只需将其添加到密文中即可。

  • 使用具有强 MAC(如 HMAC-SHA256)的 encrypt-then-MAC 方案对您的密文进行身份验证,或使用 GCM 或 EAX 等经过身份验证的操作模式。

【讨论】:

  • @artjimB 非常感谢您的出色回答。我想尝试 node-rijmdael 但正如你所说我需要先安装 libmcrypt。我没有看到用于 npm 的 libmcrypt 库。如何安装?
  • 它是 linux 的本地库,甚至可能是 windows,但我对此表示怀疑。也许那里有 Rijndael 的纯 JavaScript 实现,但我不知道。
  • Node 是否有libmcrypt 无关紧要。
  • @ScottArciszewski 为了安装库,我必须安装libmcrypt,但我不知道如何使用它?我在 Windows 上运行 Node.js。
  • @MikeA 您可以编写一个最小的 PHP 脚本来执行此操作,并通过 child_process 从 node.js 调用该 php 脚本。
猜你喜欢
  • 2012-05-06
  • 1970-01-01
  • 1970-01-01
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
  • 2020-08-19
相关资源
最近更新 更多