I'm trying to convert my symmetric AES-256-CBC encryption from PHP to NodeJS. But i think i'm not converting correctly the IV, and i tried different things, but not worked.
My PHP Code:
<?php
class Encryption{
const method = 'AES-256-CBC';
private static $passwordString;
private static $iv;
private static $password;
public static function encryptString($string){
self::setEncryptionPasswordString();
self::setEncryptionIV();
self::setEncryptionPassword();
$encrypted = openssl_encrypt($string, self::method, self::$password, OPENSSL_RAW_DATA, self::$iv);
$encrypted = base64_encode($encrypted);
$encrypted = str_replace(['+', '/', '='], ['-', '_', ''], $encrypted);
return $encrypted;
}
public static function decryptString($string){
self::setEncryptionPasswordString();
self::setEncryptionIV();
self::setEncryptionPassword();
$string = str_replace(['-', '_'], ['+', '/'], $string);
$string = base64_decode($string);
$decrypted = openssl_decrypt($string, self::method, self::$password, OPENSSL_RAW_DATA, self::$iv);
return $decrypted;
}
private static function setEncryptionPasswordString(){
self::$passwordString = getenv("ENC_PASS");
}
private static function setEncryptionIV(){
self::$iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0);
}
private static function setEncryptionPassword(){
self::$password = substr(hash('sha256', self::$passwordString, true), 0, 32);
}
}
?>
My NodeJS code:
const crypto = require("crypto");
const method = "AES-256-CBC";
const iv = Buffer.alloc(16);
const password = "my_password";
function encrypt(string){
//let key = crypto.createHash("SHA-256").update(String(password)).digest("base64").substr(0, 32); Not Working
let key = "my_iv";
let cipher = crypto.createCipheriv(method, key.substr(0, 32), iv);
let encrypted = cipher.update(string);
let result = encrypted.toString("base64").replace(/[=]/g, "").replace(/[+]/g, "-").replace(/[\/]/g, "_");
return result;
}
function decrypt(string){
}
module.exports.encrypt = (string) => encrypt(string);
module.exports.decrypt = (string) => decrypt(string);
I think, Buffer.alloc(16) is not working as i expect, and i don't know how to change it. Can someone help-me please!
The Node.js code below should give the same result as the PHP code:
Node.js
const crypto = require("crypto");
const Algorithm = "aes-256-cbc";
function encrypt(plainText, key, iv, outputEncoding = "base64") {
const cipher = crypto.createCipheriv(Algorithm, key, iv);
const output = Buffer.concat([cipher.update(plainText), cipher.final()]).toString(outputEncoding);
return output.replace('+', '-').replace('/', '_').replace('=', '');
}
function decrypt(cipherText, key, iv, outputEncoding = "base64") {
cipherText = Buffer.from(cipherText.replace('-', '+').replace('_', '/'), "base64");
const cipher = crypto.createDecipheriv(Algorithm, key, iv);
return Buffer.concat([cipher.update(cipherText), cipher.final()]).toString(outputEncoding);
}
const passwordString = "test password";
const KEY = crypto.createHash('sha256').update(passwordString).digest();
const IV = Buffer.alloc(16);
console.log("Key length (bits):", KEY.length * 8);
console.log("IV length (bits):", IV.length * 8);
const encrypted = encrypt("Brevity is the soul of wit", KEY, IV, "base64");
console.log("Encrypted (base64):", encrypted);
const decrypted = decrypt(encrypted, KEY, IV, "utf8")
console.log("Decrypted:", decrypted);
PHP
putenv('ENC_PASS=test password');
$x = new Encryption();
$encrypted = $x->encryptString("Brevity is the soul of wit");
echo "Encrypted (base64): " . $encrypted . "\r\n";
echo "Decrypted: " . $x->encryptString("Brevity is the soul of wit") . "\r\n";
Both should give an output of
IEqTyL_k1xgQaBZGFLYYfTmzytKzFgicM-5mWMyxgYw
As @robert-kawecki pointed out, you should ideally use a different IV for each encryption to ensure the best level of security.