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

0

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?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .