-1

I'm having a hard time trying to decrypt a String that has been encrypted with Blowfish CBC in PHP;

I'm working on the client side in Javascript with Node.js on a unit test written with Mocha. I'm using the inbuilt crypto functions of Node.

Here's is the code that is working to decrypt the string in PHP.

<?php
 $cipher = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_CBC, '');
 $iv = "my_iv";
 $key = substr("my_key", 0, 56);

 // I read that php automaticly pads my key with \0 to make it 56char long.

 if (mcrypt_generic_init($cipher, $key, $iv) != -1) {
   $text = mdecrypt_generic($cipher, urldecode("X%10%8F%AD%1C%1D%E1f%29%CD%D2%E1%81%B0%BE%D2M%8E3%D6%5DO%29%E3%E6%EF%24%A0%E0g%22%DA%D7YK%5B%AA%E6P%91%BA%B8U%C1%87k%7F%07%FD%9D%BF%1F%BD%95r%04%F0%18%A9%27%E17%2C%A8"));
   mcrypt_generic_deinit($cipher);
   echo rtrim($text, "\0");
 } else {
    echo "ERRROR";
 }
?>

This code give me the correct output, which is a serialised Array as a String.

I tried then two libraries to decrypt using the same flow in JS,

With crypto (inbuilt with node):

var crypto = require('crypto');
var iv = new Buffer('my_iv');
var key = new Buffer('my_key');
var text = new Buffer(unescape("X%10%8F%AD%1C%1D%E1f%29%CD%D2%E1%81%B0%BE%D2M%8E3%D6%5DO%29%E3%E6%EF%24%A0%E0g%22%DA%D7YK%5B%AA%E6P%91%BA%B8U%C1%87k%7F%07%FD%9D%BF%1F%BD%95r%04%F0%18%A9%27%E17%2C%A8"));
var decipher = crypto.createDecipheriv('bf-cbc', key, iv);
var decrypted = decipher.update(text, '', '');
    decrypted += decipher.final('');
    console.log(decrypted);

Gives me this error :

error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
at Decipheriv.Cipher.final (crypto.js:320:27)

And with the mcrypt module for node : https://github.com/tugrul/node-mcrypt

    var MCrypt = require('mcrypt').MCrypt;
    var bfCcb = new MCrypt('blowfish', 'cbc');
    var iv = Buffer.from('my_iv');
    var key = Buffer.from('my_key_padded_with_0\0\0');
    var text = Buffer.from(unescape("X%10%8F%AD%1C%1D%E1f%29%CD%D2%E1%81%B0%BE%D2M%8E3%D6%5DO%29%E3%E6%EF%24%A0%E0g%22%DA%D7YK%5B%AA%E6P%91%BA%B8U%C1%87k%7F%07%FD%9D%BF%1F%BD%95r%04%F0%18%A9%27%E17%2C%A8"));

    bfCcb.open(key, iv);

    var plaintext = bfCcb.decrypt(text);
    console.log(plaintext.toString());

It gives me the wrong output,

I don't know if it has something to do with possible encoding, or if i'm missing something with configuring my javascripts objects...

If anyone has already encountered this problem, please let me know.

tchoum
  • 312
  • 1
  • 2
  • 10
  • Blowfish should no longer be used in new code, the current choice is AES (Advanced Encryption Standard). Also it is best not to use mcrypt, it is abandonware, has not been updated in years and does not support standard PKCS#7 padding, only non-standard null padding that can't even be used with binary data. Instead consider using [defuse](https://github.com/defuse/php-encryption), it is being maintained and is correct. – zaph Apr 05 '16 at 10:30
  • Do not rely on argument padding, since there is no standard each implementation can do whatever it likes. Simply provide the correct lengths for the IV and key. – zaph Apr 05 '16 at 10:33
  • Generally either Base64 of hexadecimal is used when data must be represented in ASCII, not URL encoding. – zaph Apr 08 '16 at 11:06

1 Answers1

0

OK, ignoring security.

Note: Blowfish has a 64-bit block size and a key length of anywhere from 32 bits to 448 bits.

The error message states what the error is: "wrong final block length", that is very specific. Block based encryption requires the input to be a multiple of the block size. "my_url_encodeed_string" is 22 bytes ling which is not a multiple of the Blowfish block size of 8-bytes.

"my_url_encodeed_string" is not encrypted (encrypted appears to be random bits and bytes) so it can not be decrypted. It is also not URL encoded so there is no need to unescape.

That mcrypt does not produce an error does not mean that it successfully decrypted it's data. Blowfish encryption by itself can not tell if decryption is successful or not. Further (you are not going to like this):

It is best not to use mcrypt, it is abandonware, has not been updated in years and does not support standard PKCS#7 padding, only non-standard null padding that can't even be used with binary data. Instead consider using defuse, it is being maintained and is correct.

Further: do not rely on argument padding, since there is no standard each implementation can do whatever it likes. Simply provide the correct lengths for the IV and key.

zaph
  • 111,848
  • 21
  • 189
  • 228
  • my_url_encode_string was just a sample, but not currently the exact kind of string i'm decoding, Was just giving an example of the kind of data I'm trying to decrypt there, will update my question with a reel example. – tchoum Apr 08 '16 at 06:32