【问题标题】:Converting a PHP mcrypt() call to node's mcrypt将 PHP mcrypt() 调用转换为节点的 mcrypt
【发布时间】:2016-09-14 07:42:41
【问题描述】:

我正在尝试使用 Node 的 mycrypt 模块将旧 PHP 应用程序中的加密功能重新创建到新的 Node JS 应用程序中。

我的目标是确保给定相同的原始字符串和盐,下面的 PHP 脚本生成与 Node 脚本相同的加密值。


PHP

<?php
$string = 'This is my password';
$salt = 'sodiumChloride12';
$encrypted = base64_encode(
    mcrypt_encrypt(
        MCRYPT_RIJNDAEL_128,
        $salt,
        $string,
        MCRYPT_MODE_ECB,
        mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_RAND)
    )
);

echo "Encrypted: $encrypted\n";

它产生:

Encrypted: iOKEAxaE4vIeWXBem01gHr2wdof7ZO2dld3BuR9l3Nw=

JavaScript

var mcrypt = require('mcrypt');
var MCrypt = mcrypt.MCrypt;

// Set algorithm and mode
var rijndaelEcb = new MCrypt('rijndael-128', 'ecb');

// Set up salt and IV
var salt = 'sodiumChloride12';
var iv = rijndaelEcb.generateIv();
rijndaelEcb.open(salt, iv);

/** ENCRYPTION **/
var cipher = rijndaelEcb.encrypt('This is my password');
var cipherConcat = Buffer.concat([iv, cipher]).toString('base64');
console.log('Encrypted: ' + cipherConcat);

/** DECRYPTION **/
// Convert back from base64
var ivAndCipherText = new Buffer(cipherConcat, 'base64');

// Undo concat of IV
var ivSize = rijndaelEcb.getIvSize();
iv = new Buffer(ivSize);
var cipherText = new Buffer(ivAndCipherText.length - ivSize);
ivAndCipherText.copy(iv, 0, 0, ivSize);
ivAndCipherText.copy(cipherText, 0, ivSize);

var plaintext = rijndaelEcb.decrypt(cipherText).toString();
console.log('Decrypted: ' + plaintext);

Node 版本产生:

Encrypted: 834aJoVRxla/fGNACUAVFYjihAMWhOLyHllwXptNYB69sHaH+2TtnZXdwbkfZdzc
Decrypted: This is my password

基于它解密原始短语的事实,我知道调用按预期工作,但加密输出与 PHP 脚本中的不同。解密逻辑来自this answer,但我更关心的是让加密以同样的方式工作。

我在 Node 中的 IV 与在 PHP 中的做法不同吗?

我查看了this question,但它使用crypto 模块而不是我正在使用的mcrypt 模块。

【问题讨论】:

    标签: javascript php node.js encryption mcrypt


    【解决方案1】:

    我在 Node 中的 IV 与在 PHP 中的做法不同吗?

    嗯。代码是怎么说的?

    MCRYPT_MODE_ECB,

    var rijndaelEcb = new MCrypt('rijndael-128', 'ecb');

    您正在使用 ECB mode,它不使用 IV。您实际上是在浪费 CPU 周期来生成一个。即使您使用的是 CBC 模式,MCRYPT_RAND 也是一个不好的常量。

    var cipherConcat = Buffer.concat([iv, cipher]).toString('base64');

    您将一个未使用的 IV 连接到您的密文,并抱怨结果无效? PHP 代码只返回 cipher(在 Node.js 中的等效术语),而不是 ivcipher 的串联。


    更重要的是,这里有一些严重的密码学缺陷需要解决,从上面提到的 ECB 模式开始:

    1. Do not encrypt passwords,使用密码散列算法。 There's a huge difference
    2. 如果您要加密,use authenticated encryption
    3. Don't use mcrypt
    4. 不要deploy home-grown crypto protocols into production or encourage other developers to do the same

    推荐步骤:

    1. 使用 PHP 解密您的数据,然后存储密码 properly
    2. 如果您出于任何其他目的需要加密,use a high-level cryptography library,例如 libsodium。

    【讨论】:

    • 谢谢,我对密码学知之甚少,而且 PHP 代码是几年前由其他人编写的,所以很遗憾,我不想改变。至于 Node 版本中的 iv 连接,我在模块的 github 页面上的一个示例中看到了它,所以我认为这是正确的,但是在 Node 版本中将其全部删除是可行的,并且使解密更加清晰.
    • 我强烈建议与拨打电话的人交谈,并要求他们考虑更改加密方式以确保安全。 (如果他们不知道怎么做,我会咨询。)
    猜你喜欢
    • 2019-07-23
    • 2017-10-15
    • 2017-12-18
    • 2020-07-17
    • 2020-05-16
    • 2020-06-23
    • 2018-11-10
    • 2013-11-30
    • 2011-01-31
    相关资源
    最近更新 更多