5

I'm working on a symmetric encryption with OpenSSL using PHP and Nodejs. PHP uses the OpenSSL library, and Node.js decryption is based on the implemented crypto. The problem is that the decrypted text in Node.js is only partially correct.

PHP function for encryption

function encrypt($text, $pw, $base64 = true) {

    $method = 'aes-256-cbc';
    $iv_len = openssl_cipher_iv_length($method);
    $iv = openssl_random_pseudo_bytes($iv_len);
    
    $pw = substr(md5($pw),0,32);

    $cipher =  openssl_encrypt ($text ,$method ,$pw ,!$base64 ,$iv );

    if($base64) {
            $pw = base64_encode($pw);
            $iv = base64_encode($iv);
        }

    return array(
        'iv' => $iv,
        'pw' => $pw,
        'text' => $text,
        'cipher' => $cipher
    );
}

Decryption in nodejs

var cipher = new Buffer(data.cipher, 'base64');
var iv = new Buffer(data.iv, 'base64');
// the password is the same returned by the php function, so 100% correct
var key = new Buffer(data.pw, 'base64');
            
var dec = crypto.createDecipheriv('aes-256-cbc',key,iv);
var dec_data = dec.update(cipher,'binary','utf8');
    
// the script is based on socket.io 
socket.emit('debug',{decrypted : dec_data});

The result

# Encrypting in php...
>> encrypt('1. Lorem ipsum dolor sit amet! 2. Lorem ipsum dolor sit amet!', 'password');

# ...makes nodejs giving me something like
>> 1, 6+r@o ipsum /olor sit amet! 2. Lorem ipsum do

I'm guessing the problem might have something to do with padding - but to be honest: I have no idea.

Thanks for reading an help!

Community
  • 1
  • 1
HenningCash
  • 1,711
  • 16
  • 17
  • 1
    Have you seen [this comment](http://www.php.net/manual/en/function.openssl-encrypt.php#109598) on the PHP doc page? – Jared Farrish Aug 19 '12 at 16:09
  • So you mean I have to add (PKCS #7) padding to the text by myself, because the openssl_encrypt does't do this on its own? There is a [usercomment](http://www.php.net/manual/en/function.mcrypt-encrypt.php#105173) on the mcrypt doc-page that provides such an implemention, but this didn't work for me. – HenningCash Aug 19 '12 at 17:05
  • 1
    I don't know that `mcrypt` functions are compatible with `openssl` ones in PHP. I don't know if there's a way to fix this per se (since I don't know how to manually pad the result, seems like there should be a flag for that), but [this answer](http://stackoverflow.com/a/2613865/451969) suggests using [phpseclib](http://phpseclib.sourceforge.net/crypt/examples.html) instead of the `openssl` functions. Note the `openssl_public/private_encrypt` functions have the padding flag. – Jared Farrish Aug 19 '12 at 17:23
  • I wanted to avoid phpseclib and try the native php libs, but the phpseclib works like a charm! Maybe I'll give the openssl-lib another try but anyway: thanks! – HenningCash Aug 19 '12 at 19:42
  • You can probably look at the source and figure out how they get it to work; it does actually default to the native ssl libraries. That could give you some clues. – Jared Farrish Aug 19 '12 at 19:48
  • Regarding Mcrypt, see [Upgrading my encryption library from Mcrypt to OpenSSL](http://stackoverflow.com/q/43329513/608639), [Replace Mcrypt with OpenSSL](http://stackoverflow.com/q/9993909/608639) and [Preparing for removal of Mcrypt in PHP 7.2](http://stackoverflow.com/q/42696657/608639) – jww May 30 '17 at 22:43

1 Answers1

5

In your Node code, you are missing the final part of the message:

var dec = crypto.createDecipheriv('aes-256-cbc',key,iv);
var dec_data = dec.update(cipher,'base64','utf8') + dec.final('utf8');

Also, use base64 for your decoding, not binary (because its probably that you'll fall in the scenario mentioned here https://stackoverflow.com/a/8770975/3739618)

I have this sample code working in this other post, please check it out: https://stackoverflow.com/a/28181444/3739618

Regards, Ignacio

Community
  • 1
  • 1
inieto
  • 589
  • 9
  • 17