AES将PHP加密到NodeJS? [英] AES Encryption PHP to NodeJS?

查看:165
本文介绍了AES将PHP加密到NodeJS?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将一个小的项目从PHP迁移到NodeJS,其中包括一小部分AES加密.

I am in process of moving a small project from PHP to NodeJS that includes a small part of AES Encryption.

由于PHP代码可以正常工作,因此照常运行

As PHP code works fine, it goes as

  function decysek($data, $app_key) {
    $output = openssl_decrypt(base64_decode($data), 'AES-256-ECB', $app_key, OPENSSL_RAW_DATA);
    return $output;
  }

  function decyGetBillData($rek , $data , $decrypted_sek){
    $decrypted_rek =  openssl_decrypt(base64_decode($rek), 'AES-256-ECB', $decrypted_sek, OPENSSL_RAW_DATA);

    $decrypted_data =  openssl_decrypt(base64_decode($data), 'AES-256-ECB', $decrypted_rek, OPENSSL_RAW_DATA);
    return $decrypted_data;
  }

  $sekdec = decysek($request['sek'], $request['appKey']);
  $data = decyGetBillData($response['rek'], $response['data'], $sekdec);

  echo json_decode($data, true);

相同的NodeJS转换如下

The NodeJS Conversion of the same goes as follows

var aes256 = require("aes256");
var js_base64_1 = require("js-base64");

function decysek(data, app_key) {
    var cipher = aes256.createCipher(app_key);
    var output = cipher.decrypt(js_base64_1.Base64.decode(data));
    return output;
}
function decyGetBillData(rek, data, decrypted_sek) {
    var cipher = aes256.createCipher(decrypted_sek);
    var decrypted_rek = cipher.decrypt(js_base64_1.Base64.decode(rek));
    var cipher2 = aes256.createCipher(decrypted_rek);
    var decrypted_data = cipher2.decrypt(js_base64_1.Base64.decode(data));
    return decrypted_data;
}
var sekdec = decysek(request["sek"], request["appKey"]);
var data = decyGetBillData(response["rek"], response["data"], sekdec);
console.log(data);

NodeJS版本出了点问题,因为它无法提供输出, 而是抛出一个错误.

There is Some thing wrong with NodeJS version as it fails to give me the output, rather throws an error.

提供的加密"必须解密为非空字符串.

Provided "encrypted" must decrypt to a non-empty string.

您能找出问题所在吗?

推荐答案

NodeJS aes256模块不支持您的PHP加密算法.它使用AES-256-CTR进行加密,并使用SHA256作为密钥派生功能. IV是随机生成的,并且以密文为前缀.

The NodeJS aes256 module doesn't support your PHP encryption algorithm. It uses AES-256-CTR for encryption, and SHA256 as a key derivation function. The IV is generated randomly, and prepended to the ciphertext.

如果要使用此模块,则应该能够加密-使用以下功能在PHP中解密数据.

If you want to use this module, you should be able to encrypt - decrypt your data in PHP using the functions below.

function encrypt($plaintext, $passphrase) {
    $key = hash('SHA256', $passphrase, true);
    $iv = openssl_random_pseudo_bytes(16);
    $ct = openssl_encrypt($plaintext, 'AES-256-CTR', $key, 1, $iv);
    return base64_encode($iv.$ct);
}

function decrypt($ciphertext, $passphrase) {
    $data = base64_decode($ciphertext);
    $ciphertext = substr($data, 16);
    $key = hash('SHA256', $passphrase, true);
    $iv = substr($data, 0, 16);
    $pt = openssl_decrypt($ciphertext, 'AES-256-CTR', $key, 1, $iv);
    return $pt;
}

aes256模块在内部使用crypto. crypto是一个内置模块,它支持AES-256-ECB,因此您仍然可以将PHP代码移植到JS,但是我不建议这样做. AES-256-ECB是一种非常弱的加密算法,并且不提供身份验证.

The aes256 module is using crypto internally. crypto is a built-in module and it supports AES-256-ECB, so you could still port your PHP code to JS, but I wouldn't recommend that. AES-256-ECB is a very weak encryption algorithm, and it doesn't provide authentication.

PHP7和crypto均支持经过身份验证的加密算法,因此您可以使用GCM为例.另外,最好使用PBKDF2(PHP和crypto也支持)创建密钥.

Both PHP7 and crypto support authenticated encryption algorithms, so you could use GCM for example. Also it's best to use PBKDF2 (which is also supported by PHP and crypto) for creating the key.

使用AES-256-GCM,PBKDF2和SHA256进行PHP加密:

PHP encryption with AES-256-GCM, PBKDF2 with SHA256:

function encrypt($plaintext, $passphrase) {
    $salt = openssl_random_pseudo_bytes(16);
    $nonce = openssl_random_pseudo_bytes(12);
    $key = hash_pbkdf2("sha256", $passphrase, $salt, 40000, 32, true);
    $ciphertext = openssl_encrypt($plaintext, 'aes-256-gcm', $key, 1, $nonce, $tag);
    return base64_encode($salt.$nonce.$ciphertext.$tag);
}

function decrypt($ciphertext, $passphrase) {
    $input = base64_decode($ciphertext);
    $salt = substr($input, 0, 16);
    $nonce = substr($input, 16, 12);
    $ciphertext = substr($input, 28, -16);
    $tag = substr($input, -16);
    $key = hash_pbkdf2("sha256", $passphrase, $salt, 40000, 32, true);
    $plaintext = openssl_decrypt($ciphertext, 'aes-256-gcm', $key, 1, $nonce, $tag);
    return $plaintext;
}

使用AES-256-GCM,带有SHA256的PBKDF2进行JS加密:

JS encryption with AES-256-GCM, PBKDF2 with SHA256:

var crypto = require('crypto');

function encrypt(plaintext, passphrase) {
    var salt = crypto.randomBytes(16);
    var nonce = crypto.randomBytes(12);
    var key = crypto.pbkdf2Sync(passphrase, salt, 40000, 32, 'sha256');
    var cipher = crypto.createCipheriv('aes-256-gcm', key, nonce);
    var ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
    var output = Buffer.concat([salt, nonce, ciphertext, cipher.getAuthTag()]);
    return output.toString('base64');
}

function decrypt(ciphertext, passphrase) {
    var input = new Buffer(ciphertext, 'base64');
    var salt = input.slice(0, 16);
    var nonce = input.slice(16, 28);
    ciphertext = input.slice(28, -16);
    var tag = input.slice(-16);
    var key = crypto.pbkdf2Sync(passphrase, salt, 40000, 32, 'sha256');
    var cipher = crypto.createDecipheriv('aes-256-gcm', key, nonce);
    cipher.setAuthTag(tag);
    var plaintext = Buffer.concat([cipher.update(ciphertext), cipher.final()]);
    return plaintext.toString('utf-8');
}

这些函数产生兼容的结果,因此可以用JS中的decrypt解密PHP中用encrypt创建的密文,反之亦然.

Those functions produce compatible results, so ciphertext that is created with encrypt in PHP can be decrypted with decrypt in JS, and vice versa.

这篇关于AES将PHP加密到NodeJS?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆