php - 需要帮助使用加密将加密 Blowfish php 转换为 Nodejs
问题描述
您好,我需要帮助使用加密模块将我的 PHP 加密函数转换为 Nodejs:
此代码已经在工作
// Constructor params
$this->algorithm = "blowfish";
$this->token = "3SzzaErRzj0#RuGr@JTkh[MO0AMIW*d!Sul/CEL!*rPnq$oOEgYaH}fNw{jw1b/DyLUdL])+JOMES@Z7MIRI>(p*nY{yl%h]4ylx";
public function decrypt($string)
{
$key = hash('sha256', $this->token);
list($encrypted_data, $iv) = explode('::', base64_decode($string), 2);
return openssl_decrypt($encrypted_data, $this->algorithm, $key, 0, $iv);
}
public function encrypt($string)
{
$output = false;
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->algorithm));
// hash
$key = hash('sha256', $this->token);
$output = openssl_encrypt($string, $this->algorithm, $key, 0, $iv);
return base64_encode($output . '::' . $iv);
}
而nodejs中的代码,我使解密工作正常,但密码不工作
const crypto = require('crypto');
const decipher = async (alg, key, value) => {
const hash = crypto.createHash('sha256');
hash.update(key);
let token = hash.digest('hex');
let buff = new Buffer.from(value, 'base64');
let [encrypted, iv] = buff.toString('ascii').split('::', 2);
iv = new Buffer.from(iv);
const decipher = crypto.createDecipheriv(alg, token, iv);
let decrypted = await decipher.update(encrypted, 'base64', 'ascii');
decrypted += decipher.final('ascii');
return decrypted;
}
/* this one is not working */
const cipher = async (alg, key, value) => {
let iv = crypto.randomBytes(8);
var sha256 = crypto.createHash('sha256');
sha256.update(key);
var newkey = sha256.digest('base64');
var encryptor = await crypto.createCipheriv(alg, newkey, iv);
encrypted = encryptor.update(value, 'utf8', 'base64') + encryptor.final('base64');
var final = encrypted + "::" +iv;
let buf = Buffer.from(final);
let encodedData = buf.toString('base64');
return encodedData;
}
任何帮助我完成工作的帮助,我很感激
解决方案
cipher
在 NodeJS 代码的方法中必须进行以下更改:
密钥必须以十六进制编码:
var newkey = sha256.digest('hex');
IV 必须作为二进制字符串附加:
var final = encrypted + "::" + iv.toString('binary');
并且数据必须被解析为二进制字符串:
let buf = Buffer.from(final, 'binary');
通过这些更改, NodeJS 代码中的方法与 PHP 代码中的方法cipher
兼容。encrypt
该cipher
方法使用UTF8编码,该decipher
方法使用ASCII编码,这样只有ASCII编码的文本才能正确解密。要消除对 ASCII 编码的限制,方法中需要进行以下更改decipher
:
编码成二进制字符串必须使用
binary
而不是使用ascii
:let [encrypted, iv] = buff.toString('binary').split('::', 2); iv = new Buffer.from(iv, 'binary');
并且输出编码必须
utf8
代替ascii
:let decrypted = decipher.update(encrypted, 'base64', 'utf8'); decrypted += decipher.final('utf8');
通过这些更改,NodeJS 和 PHP 代码是兼容的。另请注意:
- 实际上,所应用的 NodeJS 函数都不是异步的,所以使用
async
/await
并不是真正必要的。 - 前面可以省略
new
。Buffer.from
- 该算法用 指定
blowfish
,对应于bf-cbc
并表示 CBC 模式下的 Blowfish。 - 使用 SHA256 生成 32 字节密钥并以十六进制字符串(64 字节/字符)形式返回,因此使用 64 字节密钥。对于 Blowfish,此处定义了 56 个字节的最大密钥长度。
- SHA256 用作密钥派生函数,更安全的是例如 PBKDF2(至少对于弱密码),here。
- 由分隔符分隔的 IV 被附加到 Base64 编码的密文中,结果数据是 Base64 编码的(即密文因此被 Base64 编码两次)。通常 IV 和密文(按此顺序)在二进制级别上连接,并且生成的数据是 Base64 编码的。分隔符不是必需的,因为 IV 的长度对应于块大小,因此是已知的。
推荐阅读
- css - 如何在我的引导和角度布局下添加图像?
- f# - 无法弄清楚如何从发电机制造发电机
- python - 如何检查以确保列表中的所有项目都属于某种类型
- angular - Angular Reactive Forms:动态生成单选按钮
- vue.js - Nuxt - $root.$children[0].config 在 Nuxt 中为空,而 $root.$children[0].config 包含 VUejs 中的数据
- mongodb - 使用不透明 ID 类型代替原语.ObjectID
- java - 为什么我的 Gradle Java 项目没有在 Intellij 中构建?
- c# - Postman 和 HttpWebRequest 给出不同的结果
- javascript - 从javascript中的嵌套对象中删除对象
- css - Django 不会加载静态 .css 文件错误:404 1689