使用 Crypto 将 PHP openssl_encrypt 与 md5 转换为 NodeJS

Posted

技术标签:

【中文标题】使用 Crypto 将 PHP openssl_encrypt 与 md5 转换为 NodeJS【英文标题】:Convert PHP openssl_encrypt with md5 to NodeJS using Crypto 【发布时间】:2021-06-01 11:05:35 【问题描述】:

我在 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));

此代码返回

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 加密,结果是一样的。

谢谢

【问题讨论】:

【参考方案1】:

Php 代码中的密钥由 MD5 散列的 16 个字节组成,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 模式通常是不安全的。加密密钥也没什么意义(但可能仅用于测试目的)。

【讨论】:

你是对的!非常感谢,我知道欧洲央行是不安全的,但客户正在使用这个密码,除了和他交谈之外,我无能为力。

以上是关于使用 Crypto 将 PHP openssl_encrypt 与 md5 转换为 NodeJS的主要内容,如果未能解决你的问题,请参考以下文章

将 Crypto++ AES 加密移植到 PHP 的 mcrypt 时密钥大小不正确

如何使用BASH命令解密PHP Openssl加密

php邮件程序中的stream_socket_enable_crypto()错误

使用 nodejs crypto 与 php 的 mcrypt 解密 Blowfish-ecb

PHPMailer 生成 PHP 警告:stream_socket_enable_crypto(): Peer certificate does not match expected

php cr_get_data_crypto.php