PHP实现OPENSSL的EVP_BytesToKey

使用PHP和nodejs进行通讯时候遇到双方加解密结果不一致的问题。

注意到crypto.createCipher(algorithm, password[, options])方法有如下的提示。

text 复制代码
The implementation of crypto.createCipher() derives keys using the OpenSSL 
function EVP_BytesToKey with the digest algorithm set to MD5, one iteration, and no salt. 

createCipher方法只接受key,不接受iv参数,iv参数是使用opensslEVP_BytesToKey方法对key进行扩展得来的,salt为空,hash算法为MD5

可以使用新的createCipheriv方法代替,但原来的NodeJs代码不能修改,只能从php方面入手修改。

简易实现-使用php对key进行扩展,再进行加解密。

php 复制代码
function EVP_BytesToKey($salt, $password) {

    $bytes = '';

    $last = '';

    while(strlen($bytes) < 48) {

        $last = hash('md5', $last . $password . $salt, true);

        $bytes.= $last;

    }

    return $bytes;

}
//从扩展结果中分离真正用于通讯的key和iv
$key = '12345678901234561234567890123456';
$devd = EVP_BytesToKey('', $key);
$key = substr($devd, 0, 32);
$iv = substr($devd, 32, 16);

@openssl_encrypt('test-data', "aes-256-cbc", $key,  1, $iv);

nodejs直接使用key进行加解密

js 复制代码
const key = '12345678901234561234567890123456';
crypto.createCipher("aes-256-cbc", key)

EVP_BytesToKey的完整实现

php 复制代码
/**
 * @param string $password
 * @param int $nkey 需要生成的密钥长度
 * @param int $niv 需要生成的iv长度
 * @param string $hash HASH算法,默认MD5
 * @param string $salt salt。默认为空
 * @param int $round HASH运行轮数
 * @return array
 */
function EVP_BytesToKey(string $password, int $nkey = 32, int $niv = 16, string $hash = 'md5', string $salt = '', int $round = 1): array
{
    $bytes = '';
    $last = '';
    $total = $nkey + $niv;

    while (strlen($bytes) < $total) {
        $last = hash($hash, $last . $password . $salt, true);

        for ($i = 1; $i < $round; $i++) {
            $last = hash($hash, $last, true);
        }
        $bytes .= $last;
    }

    return [
        'key' => substr($bytes, 0, $nkey),
        'iv' => substr($bytes, $nkey, $niv),
    ];

}

更多语言实现

https://github.com/sometiny/evp_bytestokey

相关推荐
lzhdim12 分钟前
SharpCompress:跨平台的 C# 压缩与解压库
开发语言·c#
嘿嘿嘿x317 分钟前
Linux记录过程
linux·开发语言
默 语25 分钟前
Records、Sealed Classes这些新特性:Java真的变简单了吗?
java·开发语言·python
止观止26 分钟前
拥抱 ESNext:从 TC39 提案到生产环境中的现代 JS
开发语言·javascript·ecmascript·esnext
卷心菜狗36 分钟前
Python进阶-深浅拷贝辨析
开发语言·python
时寒的笔记37 分钟前
js逆向7_案例惠nong网
android·开发语言·javascript
Evand J1 小时前
【MATLAB例程】基于低精度IMU、GNSS的UAV初始航向(三维角度)校准的仿真,包含卡尔曼滤波、惯导解算与校正
开发语言·matlab·gnss·imu·卡尔曼滤波
feng_you_ying_li1 小时前
c++之哈希表的介绍与实现
开发语言·c++·散列表
网域小星球1 小时前
C 语言从 0 入门(十四)|文件操作:读写文本、保存数据持久化
c语言·开发语言·文件操作·fopen·fprintf
网域小星球1 小时前
C 语言从 0 入门(七)|字符数组与字符串完整精讲|VS2022 高质量实战
c语言·开发语言·字符串·vs2022·字符数组