需要帮助使用加密将 Encryption Blowfish php 转换为 Nodejs
Need Help to convert Encryption Blowfish php to Nodejs using crypto
您好,我需要帮助使用加密模块将我的 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 中的代码,我使 decipher 工作正常,但 cipher 不工作
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;
}
感谢任何帮助我完成工作的帮助
必须在 NodeJS 代码的 cipher
方法中进行以下更改:
密钥必须为十六进制编码:
var newkey = sha256.digest('hex');
IV 必须作为二进制字符串附加:
var final = encrypted + "::" + iv.toString('binary');
并且数据必须解析为二进制字符串:
let buf = Buffer.from(final, 'binary');
通过这些更改,NodeJS 代码中的 cipher
方法与 PHP 代码中的 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 代码兼容。另请注意:
- 实际上 none 应用的 NodeJS 函数是异步的,所以
async
/await
的使用并不是真正必要的。
Buffer.from
前的new
可以省略
- 算法指定为
blowfish
,对应bf-cbc
,表示CBC模式下的Blowfish。
- 一个 32 字节的密钥是用 SHA256 生成的,并作为十六进制字符串返回(64 bytes/chars),因此使用了一个 64 字节的密钥。对于 Blowfish,定义了 56 字节的最大密钥长度,here.
- 使用SHA256作为密钥推导函数,更安全例如PBKDF2(至少对于弱密码),here.
- 用定界符分隔的IV附加到Base64编码的密文,结果数据是Base64编码的(即密文因此被Base64编码两次)。通常 IV 和密文(按此顺序)在二进制级别连接,结果数据采用 Base64 编码。不需要分隔符,因为 IV 的长度对应于块大小,因此是已知的。
您好,我需要帮助使用加密模块将我的 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 中的代码,我使 decipher 工作正常,但 cipher 不工作
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;
}
感谢任何帮助我完成工作的帮助
必须在 NodeJS 代码的 cipher
方法中进行以下更改:
密钥必须为十六进制编码:
var newkey = sha256.digest('hex');
IV 必须作为二进制字符串附加:
var final = encrypted + "::" + iv.toString('binary');
并且数据必须解析为二进制字符串:
let buf = Buffer.from(final, 'binary');
通过这些更改,NodeJS 代码中的 cipher
方法与 PHP 代码中的 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 代码兼容。另请注意:
- 实际上 none 应用的 NodeJS 函数是异步的,所以
async
/await
的使用并不是真正必要的。 Buffer.from
前的new
可以省略- 算法指定为
blowfish
,对应bf-cbc
,表示CBC模式下的Blowfish。 - 一个 32 字节的密钥是用 SHA256 生成的,并作为十六进制字符串返回(64 bytes/chars),因此使用了一个 64 字节的密钥。对于 Blowfish,定义了 56 字节的最大密钥长度,here.
- 使用SHA256作为密钥推导函数,更安全例如PBKDF2(至少对于弱密码),here.
- 用定界符分隔的IV附加到Base64编码的密文,结果数据是Base64编码的(即密文因此被Base64编码两次)。通常 IV 和密文(按此顺序)在二进制级别连接,结果数据采用 Base64 编码。不需要分隔符,因为 IV 的长度对应于块大小,因此是已知的。