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.

9
  • The IV's must be same and the keys Commented Jan 12, 2019 at 6:50
  • They are. I've been trying to do this with hashed key/iv and unhashed, but the issue remains. Commented Jan 12, 2019 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 Commented Jan 12, 2019 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. Commented Jan 13, 2019 at 2: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. Commented Jan 13, 2019 at 9:22

1 Answer 1

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

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!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.