使用加密将 PHP openssl_encrypt 与 md5 转换为 NodeJS

Convert PHP openssl_encrypt with md5 to NodeJS using Crypto

我在PHP中有这段代码(无法修改)

<?php
$myPlain = "123456789012345678900000";
$myKey = md5($myPlain, true);
$myKey .= substr($myKey, 0,8);
$encrypted = openssl_encrypt($myPlain, 'des-ede3', $myKey, OPENSSL_RAW_DATA);
print(base64_encode($encrypted));

此代码returns

FTYDrZTZMjVBv5Fk/xcfFxJASaizzrmoPts7fGDvWjc=

当我尝试在 NodeJS 中复制它时

function testEde3(myKey, myPlain) {
    try {
        let md5Key = crypto.createHash('md5').update(myKey, 'utf-8').digest("base64").substr(0, 24);
        console.log(md5Key); //outputs 4o1aJrSWN3bSfjuIX6VXgA==

        console.log(md5Key.length); //outputs 24

        const cipher = crypto.createCipheriv('des-ede3', md5Key, null);
        
        let encrypted = cipher.update(myPlain, 'utf8', 'base64');
        encrypted += cipher.final('base64');
        return encrypted;
    } catch ( ex ) {
        return ex;
    }
}
const myKey = "123456789012345678900000";
const myPlain = "123456789012345678900000";
const hash = testEd3(myKey, myPlain);
console.log(`Hash is: ${hash}`);

输出为

Hash is: lDQX9OGsopKOt6P9WQwekGsKDQGFpfGW50zbs3HrOfQ=

我认为问题出在 MD5 上。如果我尝试不使用 md5 加密,结果是一样的。

谢谢

Php 代码中的密钥由 16 个字节的 MD5 散列组成,MD5 散列的前 8 个字节附加到此,从而产生一个 24 字节的密钥(根据 3DES 的要求)。这目前没有在 NodeJS 代码中实现,但可以实现,例如通过:

let md5Key = crypto.createHash('md5').update(myKey, 'utf-8').digest();
md5Key = Buffer.concat([md5Key, md5Key.slice(0, 8)]);

通过此更改,NodeJS 代码使用相同的输入数据生成 PHP 代码的密文。

des-ede3表示ECB模式下的3DES。请注意,3DES 已过时且速度慢,应由 AES 取代。 ECB 模式通常是不安全的。加密密钥也没什么意义(但可能仅用于测试目的)。