Javascript 使用加密模块对NodeJS进行PHP-AES加密
我的任务是遵循给定的、有效的PHP加密到node.js中。使用任何节点模块包。我不需要做解密,因为它已经存在于他们的API中,我只需要将加密的值传递给他们的API进行解密,这是在PHP中。我尝试使用节点加密和分离md5模块。以下是伪代码:Javascript 使用加密模块对NodeJS进行PHP-AES加密,javascript,php,node.js,encryption,node-crypto,Javascript,Php,Node.js,Encryption,Node Crypto,我的任务是遵循给定的、有效的PHP加密到node.js中。使用任何节点模块包。我不需要做解密,因为它已经存在于他们的API中,我只需要将加密的值传递给他们的API进行解密,这是在PHP中。我尝试使用节点加密和分离md5模块。以下是伪代码: 数据加密算法 创建一个16字节的随机salt和hash。每次你打电话时,盐都是新创建的 API 散列提供的加密密钥 使用“AES-128-CBC”进行加密,并将散列的salt值用作向量和散列 加密密钥 为salt添加前缀并附加加密数据 执行Base64编码
- 数据加密算法
- 创建一个16字节的随机salt和hash。每次你打电话时,盐都是新创建的 API
- 散列提供的加密密钥
- 使用“AES-128-CBC”进行加密,并将散列的salt值用作向量和散列 加密密钥
- 为salt添加前缀并附加加密数据
- 执行Base64编码
- JSON编码和post请求
$data = json_encode([
'username' => "jCpVyf3VEt",
'password' => "eGD6TWKmnn",
'account_no' => "0030300155398",
'tran_date' => "08/06/2019 10:30:45",
'reference_no' => "12328ALHYGZC20",
'area' => "JENRA DAU"]);
function encrypt( $data) {
$key = md5("IfZDGbVDHTxlJIkK", true);
$cipher = "aes-128-cbc";
$salt = openssl_random_pseudo_bytes(16);
$iv = md5( $salt, true);
$encrypted_bin = $salt . openssl_encrypt( serialize( $data ), $cipher, $key, true, $iv);
$encrypted_str = base64_encode( $encrypted_bin);
return $encrypted_str;
}
echo encrypt($data);
出于测试目的,以下是API中用于解密的PHP代码:
$data = 'LI5BJJw1PEhWellnjKEt3g9oaHs8uDDknBT2qDNI7Rfs644+IjobOaFxlrIrOvDm7dkASRsOTu4Yuxzi4I5q29QoE5huH6y4/XZXsResZjLPidv1ToTnhB2UKXH5rX/g/8Od7ljO6VLVAS7zx+94xeOgtpP/idkkpDi1fRNGvnOkl1c6fcyVhwl2Pv+ijKSK9+ou+54dfQrCng2uBzKC6RrHY3lvP7ktsSvtnkXFqksrpjfJ2gnMH6sMIMzru1+D';
function decrypt($encrypted) {
$cipher = "aes-128-cbc";
$key = md5("IfZDGbVDHTxlJIkK", true);
$data = base64_decode($encrypted);
$salt = substr($data, 0, 16);
$iv = md5($salt, true);
$decrypted_bin = openssl_decrypt(substr($data, 16, strlen($data)), $cipher, $key, true, $iv);
if($decrypted_bin === false) {
return json_encode([ -102 => "Authentication Failed"]);
}
return unserialize( $decrypted_bin);
}
echo decrypt($data);
运行PHP加密代码会导致来自PHP解密的成功响应。但是当我运行Node.js加密时,我能够获得加密数据,但是当我测试Node.js中的加密数据并将加密值发送到PHP解密代码时,结果是身份验证错误。似乎我无法将PHP加密算法转换为节点
.js这是一个非常有趣的例子。。我认为主要的问题是在Node.js中连接salt和加密数据的方法 我发现下面的代码工作得很好,它给出了与PHP代码相同的结果 注意,我在这里使用的是一个固定的salt(从固定的base64字符串解码),因为这给了我们一个确定性的输出。您可能应该切换到在生产中使用crypto.randomBytes 此外,PHP在json输出中将“/”编码为“\/”,请参阅。这当然可以在PHP中配置(在JSON_encode中使用标志JSON_UNESCAPED_SLASHES),但我怀疑在您的情况下无法更改。这就是为什么我在json明文中将“/”替换为“\/”
const reqBody = {
"username": "jCpVyf3VEt",
"password": "eGD6TWKmnn",
"account_no": "0030300155398",
"tran_date": "08/06/2019 10:30:45",
"reference_no": "12328ALHYGZC20",
"area": "JENRA DAU"
};
const Serialize = require('php-serialize')
const md5 = require('md5');
//encrypt
const crypto = require('crypto'),
algorithm = 'aes-128-cbc',
key = 'IfZDGbVDHTxlJIkK',
inputEncoding = 'utf8',
outputEncoding = 'base64';
function encrypt(input, key, salt) {
let serialized = Serialize.serialize(input);
let iv = md5(salt);
let hKey = md5(key);
let cipher = crypto.createCipheriv(algorithm, Buffer.from(hKey, 'hex'), Buffer.from(iv, 'hex'));
let crypted = cipher.update(serialized, inputEncoding);
let encrypted = Buffer.concat([salt, crypted, cipher.final()]);
return encrypted.toString(outputEncoding);
}
// We must escape forward slashes here, since this is how PHP will behave.
let data = JSON.stringify(reqBody).replace(/\//ig, "\\/");
// We can use any random salt here, e.g. crypto.randomBytes For this example we'll use the same as the existing encrypted data.
let salt = Buffer.from('LI5BJJw1PEhWellnjKEt3g==', 'base64');
console.log("Encrypted data: ", encrypt(data, key, salt));
谢谢terry,即使是随机生成的salt 16字节,它现在也可以工作了。我想知道为什么你这么容易就解决了我的问题?为此工作了不少于8小时。试错这不容易:-)这是一个难题。我刚刚比较了PHP和Node.js之间的各种中间阶段,我以前也处理过类似的问题!好吧我现在可以睡个好觉了,我有信心明天能赶上最后期限!非常感谢你的尊重!
const reqBody = {
"username": "jCpVyf3VEt",
"password": "eGD6TWKmnn",
"account_no": "0030300155398",
"tran_date": "08/06/2019 10:30:45",
"reference_no": "12328ALHYGZC20",
"area": "JENRA DAU"
};
const Serialize = require('php-serialize')
const md5 = require('md5');
//encrypt
const crypto = require('crypto'),
algorithm = 'aes-128-cbc',
key = 'IfZDGbVDHTxlJIkK',
inputEncoding = 'utf8',
outputEncoding = 'base64';
function encrypt(input, key, salt) {
let serialized = Serialize.serialize(input);
let iv = md5(salt);
let hKey = md5(key);
let cipher = crypto.createCipheriv(algorithm, Buffer.from(hKey, 'hex'), Buffer.from(iv, 'hex'));
let crypted = cipher.update(serialized, inputEncoding);
let encrypted = Buffer.concat([salt, crypted, cipher.final()]);
return encrypted.toString(outputEncoding);
}
// We must escape forward slashes here, since this is how PHP will behave.
let data = JSON.stringify(reqBody).replace(/\//ig, "\\/");
// We can use any random salt here, e.g. crypto.randomBytes For this example we'll use the same as the existing encrypted data.
let salt = Buffer.from('LI5BJJw1PEhWellnjKEt3g==', 'base64');
console.log("Encrypted data: ", encrypt(data, key, salt));