0

I have been trying to find out how to make this:

function encrypt_decrypt($action, $string) {
    $output = false;

    $encrypt_method = "AES-256-CBC";
    $secret_key = 'HqFdkh2FX126fH1r';
    $secret_iv = 'iS2dk82dXd26f61K';

    // hash
    $key = hash('sha256', $secret_key);

    // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
        $iv = substr(hash('sha256', $secret_iv), 0, 16);

    if ( $action == 'encrypt' ) {
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
    } else if( $action == 'decrypt' ) {
        $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
    }

    return $output;
}

In Node.js

The reason is that the encryption will be handled by PHP and the decryption by Node.

EDIT:

I managed to get this far:

var crypto = require('crypto')
            , key = 'cI8Jd96NDoasd09jcI8Jd96NDoasd09j'
            , iv = 'cI8Jd96NDoasd09j'
            , plaintext = '2';

            hashedKey = crypto.createHash('sha256').update(key, 'utf-8').digest('hex');
            console.log('hashed key=', hashedKey);
            // corresponds to the hashed key in PHP

            hashedIv = crypto.createHash('sha256').update(iv, 'utf-8').digest('hex').substring(0,16);
            console.log('hashed iv=', hashedIv);
            // corresponds to the hashed iv in PHP

            var buf = Buffer.from(teamId, 'base64');
            console.log("buffer: " + buf);

and the variable buf actually is the same as base64_decode($string in the PHP code.

However, when I do this:

    var decipher = crypto.createDecipheriv("aes-256-cbc",key, iv);
    var decrypted = decipher.update(buf,  'base64', 'utf8');
    console.log("decrypted.toString(): " + decrypted.toString());

I'm getting Z���ߋd�M:�� in the console rather than the desired 2.

djokerndthief
  • 455
  • 2
  • 4
  • 16
  • The IV's must be same and the keys – kelalaka Jan 12 '19 at 06:50
  • They are. I've been trying to do this with hashed key/iv and unhashed, but the issue remains. – djokerndthief Jan 12 '19 at 16:51
  • Let me correct, the key in the php is `HqFdkh2FX126fH1r` and JS `cI8Jd96NDoasd09jcI8Jd96NDoasd09j` and where is decryption part? Did you see [this](https://stackoverflow.com/questions/41222162/encrypt-in-php-openssl-and-decrypt-in-javascript-cryptojs) – kelalaka Jan 12 '19 at 16:56
  • I understand. I tried putting the same key, but after hashing it (as I do in PHP) node complains that the key and iv are too many characters. – djokerndthief Jan 13 '19 at 02:44
  • That's because you hex-encode your digest, so your key is a string of 64 characters. PHP's `hash()` also hex-encodes the hash by default; it returns raw bytes if the `$raw_output` parameter is set to true. – t.m.adam Jan 13 '19 at 09:22
  • I'm a bit confused. What do you propose I do? – djokerndthief Jan 13 '19 at 18:35
  • This in PHP: `$secret_key = 'cI8Jd96NDoasd09jcI8Jd96NDoasd09j'; $key = hash('sha256', $secret_key);` Makes `$key = 31bffd16a153c5358b1e3d57751630a46cf0735dffa68b76a54ada32d4a41a87` And this in node: `key = 'cI8Jd96NDoasd09jcI8Jd96NDoasd09j' hashedKey = crypto.createHash('sha256').update(key, 'utf-8').digest('hex');` Makes `haskedKey = 31bffd16a153c5358b1e3d57751630a46cf0735dffa68b76a54ada32d4a41a87` iv in PHP and Node both also returns `beb10b6636acf20d` So the iv and key are the same but it's the last part that doesn't seem to work as needed. – djokerndthief Jan 13 '19 at 18:57
  • `base64_decode($string)` in PHP is also equal to `buf` in Node. – djokerndthief Jan 13 '19 at 19:00
  • I have now changed to: `key = 'This is my secret key' iv = 'This is my secret iv'` in both PHP and Node and am getting the same hash for both of them as well. But when I get the result from Node for this: `var decipher = crypto.createDecipheriv("aes-256-cbc",hashedKey, hashedIv); var decrypted = decipher.update(buf, 'base64', 'utf8');` I am not getting the desired result '2' - which I do from PHP. – djokerndthief Jan 13 '19 at 20:17

1 Answers1

3

The main problem was an embarrasing one. We are mainly two devs on this project and I thought the php-file I was editing for the encryption and decryption was the only thing I had to care about.

It was later realized that the actual call for the encoding was made from another php-file. Thus, what I changed in the encoding in the file I was working on was all in vain.

The end result looks like this, for anyone who's interested:

    function encrypt_decrypt($action, $string) {
    $output = false;

    $encrypt_method = "AES-256-CBC";
    $secret_key = '32 byte key';
    $secret_iv = '16 byte iv';

    // hash
    $key = substr(hash('sha256', $secret_key), 0, 32);

    // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
        $iv = substr(hash('sha256', $secret_iv), 0, 16);

        if ( $action == 'encrypt' ) {
                $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
                //$output = base64_encode($output);
        } else if( $action == 'decrypt' ) { // this below is now handled in Node
                $output = openssl_decrypt($string, $encrypt_method, $key, 0, $iv);
                //$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
        }
    return $output;
}

And Node:

function getDecryptedTeamId(encryptedId) {
    var hashedKey;
    var hashedIv;
    var crypto = require('crypto')
    , key = 'same 32 byte key as above in php'
    , iv = 'same 16 byte ivas above in php'
    , plaintext = '2';

    hashedKey = crypto.createHash('sha256').update(key, 'utf-8').digest('hex').substring(0,32);
    key = hashedKey;

    hashedIv = crypto.createHash('sha256').update(iv, 'utf-8').digest('hex').substring(0,16);
    iv = hashedIv;

    var buf = Buffer.from(encryptedId, 'base64');
    var crypt = buf.toString('base64');

    var decryptor = crypto.createDecipheriv("aes-256-cbc", hashedKey, hashedIv);
    var teamIdDec = decryptor.update(buf);
    teamIdDec += decryptor.final();
    return teamIdDec;
}
djokerndthief
  • 455
  • 2
  • 4
  • 16
  • 1
    I haven't been having great fun with AWS KMS, it works on some devices and it decides not to work on other devices. So far, this has been working as anticipated - thank you! – Cam Apr 11 '19 at 22:09