0

I have a PHP script used to encrypt data with openssl_encrypt() and the aes-256-cbc algo. Encryption/Decryption works well using PHP, it's an old script. I've been trying to decrypt the datas using NodeJS and the crypto module.

Information used for debug purpose:

base64 string stored in DB , that contains : encrypted_data_b64 + iv (format : encrypted_data_b64::iv)

This is generated by the php script .

T3FWbE1GRU5uUlFPNFpJOEpwR25zU1pTeWlHdU55S2FYMnFhc3c3MHVMZz06OsDI5XgOUrIoo+IAu8sYoXw=

Here is the base64 format key:

alFlTFNKNGtLYXhtNkpOa2tHUEs=

Here is the base64 format IV:

wMjleA5Ssiij4gC7yxihfA==

Here is the encrypted data , base64 format:

OqVlMFENnRQO4ZI8JpGnsSZSyiGuNyKaX2qasw70uLg=

Are you able to make a NODEJS example file that will decode the data from the string stored in BD ?

As an example, here is the PHP script used. I have been trying a lot of option using node but always get errors or not the correct description.

<?php
function Encrypt($data)
{
    // Remove the base64 encoding from our key
    $encryption_key = base64_decode("alFlTFNKNGtLYXhtNkpOa2tHUEs=");
    // Generate an initialization vector
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
    // Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector.
    $encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv);
    // The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::)
    return base64_encode($encrypted . '::' . $iv);
};

function Decrypt($data)
{
    // Remove the base64 encoding from our key
    $encryption_key = base64_decode("alFlTFNKNGtLYXhtNkpOa2tHUEs");
    // plain $encryption_key = "jQeLSJ4kKaxm6JNkkGPK";

    // To decrypt, split the encrypted data from our IV - our unique separator used was "::"
    list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
    return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
}


//echo "Here is the encrypted password:" . Encrypt("mysecurepassword");
//echo "<br><br>";
//echo "here is the decrypted password:" . Decrypt(Encrypt("mysecurepassword"));

    $data = "T3FWbE1GRU5uUlFPNFpJOEpwR25zU1pTeWlHdU55S2FYMnFhc3c3MHVMZz06OsDI5XgOUrIoo+IAu8sYoXw=";
    // Remove the base64 encoding from our key
    $encryption_key = base64_decode("alFlTFNKNGtLYXhtNkpOa2tHUEs");
    // plain $encryption_key = "jQeLSJ4kKaxm6JNkkGPK";

    // To decrypt, split the encrypted data from our IV - our unique separator used was "::"
    list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
    echo "This is the IV : " .base64_encode($iv);
    echo '<br>';
    echo openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
    echo '<br>';
    echo openssl_cipher_iv_length('aes-256-cbc');
    echo '<br>'; 
    echo $encrypted_data;
?> 

Thanks for your help and your time :) I hope it will help other people too.

1 Answer 1

1

Here you go :

The problem is that the base64 key used is not 32chars. In PHP, openssl_decrypt probably add the missing chars with '\0' So when when decrypted, it was always invalid key length.

const crypto = require("crypto"); // Import the crypto module
const algorithm = "aes-256-cbc"; // Use AES 256-bit encryption
const key = "jQeLSJ4kKaxm6JNkkGPK\0\0\0\0\0\0\0\0\0\0\0\0"; // <====== php accept less than 32char for key and just add \0 to have 32chars or 256 bytes
//const iv = crypto.randomBytes(16); // Generate a random 16-byte IV

function encrypt(data, ivData) {
  // Function to encrypt data
  let cipher = crypto.createCipheriv(algorithm, Buffer.from(key), ivData);
  let encrypted = cipher.update(data);
  encrypted = Buffer.concat([encrypted, cipher.final()]);
  return {
    ivData: ivData.toString("base64"),
    encryptedData: encrypted.toString("base64")
  };
}

function decrypt(encryptedData, ivData) {
  // Function to decrypt data
  let encryptedText = Buffer.from(encryptedData, "base64");
  let decipher = crypto.createDecipheriv(algorithm, Buffer.from(key), ivData);
  let decrypted = decipher.update(encryptedText);
  decrypted = Buffer.concat([decrypted, decipher.final()]);
  return decrypted.toString();
}

const ivNew = Buffer.from("wMjleA5Ssiij4gC7yxihfA==", "base64");

var encrypted = encrypt(data, ivNew); // Encrypt the data
console.log("Encrypt Data: ", encrypted);

const dataENC = "OqVlMFENnRQO4ZI8JpGnsSZSyiGuNyKaX2qasw70uLg=";
var decrypted = decrypt(dataENC, ivNew); // Decrypt the data
console.log("Decrypt Data: ", decrypted);

And the other problem I am facing is that NodeJS in not able to convert the original IV from it's saved format to base64.

This base64 :

T3FWbE1GRU5uUlFPNFpJOEpwR25zU1pTeWlHdU55S2FYMnFhc3c3MHVMZz06OsDI5XgOUrIoo+IAu8sYoXw=

Has the encrypted data in base64 format + the IV original chars (I don't know the encoding type...)

But with Node I am not able to take that IV chars and encode it into base64 . The result is not the one expected. If you have any ideas please share .

The following does not work :

const stringRef = "T3FWbE1GRU5uUlFPNFpJOEpwR25zU1pTeWlHdU55S2FYMnFhc3c3MHVMZz06OsDI5XgOUrIoo+IAu8sYoXw=" 
const stringRefDecoded = Buffer.from(
  stringRef,
  'base64'
).toString('utf8');
const pwd_iv_arr = stringRefDecoded.split('::',2);
console.log (pwd_iv_arr);
let password = pwd_iv_arr[0];
let iv = Buffer.from(pwd_iv_arr[1], 'binary').toString('base64');
console.log(iv);

Result from node :

/f39eA5S/Sj9/QD9/Rj9fA==

Result from PHP:

wMjleA5Ssiij4gC7yxihfA==

Why is that?

1
  • Thanks for this. It resolved my issue converting PHP to Node.JS whereby I had to pad the key with "\0", so just adjusted const key = 'passphrase'.padEnd(32, '\0'); Commented Apr 13, 2024 at 11:23

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.