The Node.js aes256 module doesn't support your PHP encryption algorithm, AES-256-ECB. It uses AES-256-CTR for encryption, and SHA256 as a key derivation function. The IV is generated randomly, and prepended to the ciphertext.
If you want to use this module, you should be able to encrypt - decrypt your data in PHP using the functions below.
/**
* Encrypts data with the supplied passphrase, using AES-256-CTR.
*
* @param string $plaintext the plaintext data.
* @param string $passphrase a passphrase/password.
* @return string|false encrypted data: iv + ciphertext or `false` on error.
*/
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);
}
/**
* Decrypts data with the supplied passphrase, using AES-256-CTR.
*
* @param string $ciphertext encrypted data.
* @param string $passphrase a passphrase/password.
* @return string|false plaintext data or `false` on error.
*/
function decrypt($ciphertext, $passphrase) {
$data = base64_decode($ciphertext);
$ciphertext = substr($data, 16);
$key = hash('SHA256', $passphrase, true);
$iv = substr($data, 0, 16);
return openssl_decrypt($ciphertext, 'AES-256-CTR', $key, 1, $iv);
}
The aes256 module is using crypto internally, which 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.
Both PHP7 and crypto support authenticated encryption algorithms, so you could use GCM for example. Also it's best to use a KDF, like PBKDF2 (which is also supported by PHP and crypto) for creating the key.
PHP encryption with AES-256-GCM, PBKDF2 with SHA256:
/**
* Encrypts data with the supplied passphrase, using AES-256-GCM and PBKDF2-SHA256.
*
* @param string $plaintext the plaintext data.
* @param string $passphrase a passphrase/password.
* @return string|false encrypted data: salt + nonce + ciphertext + tag or `false` on error.
*/
function encrypt(string $plaintext, string $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);
}
/**
* Decrypts data with the supplied passphrase, using AES-256-GCM and PBKDF2-SHA256.
*
* @param string $ciphertext encrypted data.
* @param string $passphrase a passphrase/password.
* @return string|false plaintext data or `false` on error.
*/
function decrypt(string $ciphertext, string $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);
return openssl_decrypt($ciphertext, 'aes-256-gcm', $key, 1, $nonce, $tag);
}
JS encryption with AES-256-GCM, PBKDF2 with SHA256:
const crypto = require('crypto');
/**
* Encrypts data with the supplied passphrase, using AES-256-GCM and PBKDF2-SHA256.
*
* @param {String} $plaintext the plaintext data.
* @param {String} $passphrase a passphrase/password.
* @return {String} encrypted data: salt + nonce + ciphertext + tag.
*/
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');
}
/**
* Decrypts data with the supplied passphrase, using AES-256-GCM and PBKDF2-SHA256.
*
* @param {String} $ciphertext encrypted data.
* @param {String} $passphrase a passphrase/password.
* @return {String} plaintext data.
*/
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');
}
Those functions produce compatible results, so ciphertext that is created with encrypt in PHP can be decrypted with decrypt in JS, and vice versa. Of course, this is just a basic example, production code would have more features, exception handling and possibly settings for the cipher and KDF.