0

I have an old PHP project which I am converting to Node JS. The PHP project had AES-256-CBC encryption and decryption method which I want to use in Node JS too.

PHP

<?php

  function encrypt($plain_text) {
    $method = 'aes-256-cbc';
    $key = 'crocodile';

    $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);

    $encrypted = base64_encode(openssl_encrypt($plain_text, $method, $key, OPENSSL_RAW_DATA, $iv));
    return $encrypted;
}

  function decrypt($encryptedMessage){
    $method = 'aes-256-cbc';
    $key = 'crocodile';

    $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);

    $decrypted = openssl_decrypt(base64_decode($encryptedMessage), $method, $key, OPENSSL_RAW_DATA, $iv);
    return $decrypted;
}

?>

NODE JS

var crypto = require('crypto');

var encrypt = function (plain_text) {
    var encryptionMethod = 'AES-256-CBC';
    var secret = "crocodile";
    var iv = crypto.randomBytes(16);
    var encryptor = crypto.createCipheriv(encryptionMethod, secret, iv);
    return encryptor.update(plain_text, 'utf8', 'base64') + encryptor.final('base64');
};

var decrypt = function (encryptedMessage) {
    var encryptionMethod = 'AES-256-CBC';
    var secret = "crocodile";
    var iv = crypto.randomBytes(16);
    var decryptor = crypto.createDecipheriv(encryptionMethod, secret, iv);
    return decryptor.update(encryptedMessage, 'base64', 'utf8') + decryptor.final('utf8');
};

The Node JS code is mostly copied from this answer: https://stackoverflow.com/a/28181444/6699134

The problem is that node js requires a 32 character secret key and I am not sure why it worked in PHP with only 9 letter secret key. Currently this node js code throws error: Invalid key length - which is obvious that it requires 32 character key. Any help will be greatly appreciated

  • 1
    PHP silently pads too short keys with 0x00 values at the end, just as it shortens too long keys (which is actually a bad design). Since you are using AES-256, i. e. a 32 bytes key, your 9 character key is also silently extended in the PHP code. – Topaco Oct 07 '21 at 10:39
  • 1
    If you want to use a password instead of a key, you should use a reliable key derivation function like PBKDF2. By the way, a static IV (e.g. one that consists only of 0x00 values as in the PHP code) is insecure. – Topaco Oct 07 '21 at 10:41
  • Apply a random IV, like in the NodeJS code. The decryption must use the IV from the encryption (which however does not seem to be the case in the NodeJS code, so decryption may fail). – Topaco Oct 07 '21 at 10:50
  • @Topaco I see, then is there any way to add pads to the key in Node JS code with static IV. We have hundreds of users who will lose login access if I implement a new secret key with dynamic iv – Abhinandan Chakraborty Oct 07 '21 at 10:55
  • 1
    The NodeJS code works. You just need to append 0x00 values to the key until it has a size of 32 bytes, and use an IV that consists of only 0x00 values. Note that the PHP code is insecure (as mentioned above). Also, for authentication/login, no encryption but hashing should be used. – Topaco Oct 07 '21 at 14:34
  • @Topaco Thanks for your answer. I finally got some time to test out this code and indeed it worked. All I added for key: `"crocodile".padEnd(32, "\0");` and for iv: `"".padEnd(16, "\0")` It's definitely not safe method as you mentioned but your answer did guide me to the right solution. Please add your comment to the answer and I will accept it. Thanks – Abhinandan Chakraborty Oct 25 '21 at 12:35

0 Answers0