Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with PHP5.6's openssl AES #194

Open
TaiTair opened this issue Feb 11, 2021 · 10 comments
Open

Compatibility with PHP5.6's openssl AES #194

TaiTair opened this issue Feb 11, 2021 · 10 comments
Labels
support Questions asking about how to use the library, like StackOverflow.

Comments

@TaiTair
Copy link

TaiTair commented Feb 11, 2021

Hi,

I am currently trying to develop an API for a flutter-based mobile app.

I've been having some really strange issues that make me think this module does not use the same algorithms as PHP.
For example:
If I encrypt the word "Ping" from flutter with my secret key and my IV set to 16 0 bytes then I get: "kU1IVV86Aw7Iuub8KuxmYw=="
If I encrypt the same word from PHP5.6 with the same secret key and same IV then I get: "QdKmZQ=="
Note: I encode the encrypted result in base64.

Here's where it gets really, really strange though:

If I encrypt the word "Ping" from flutter and send it to my API, then decrypt it in PHP and log the decrypted result I get a bad string that seems to be some kind of encoding error or an empty string. But then if I re-encrypt the decrypted message with PHP's functions and send it back it is a perfect copy of the original string: "kU1IVV86Aw7Iuub8KuxmYw=="

What in the world is going on? If I encrypt it straight from PHP I get a different encrypted message but if I send it from flutter, decrypt it in PHP then re-encrypt it in PHP i get the exact same message?
If I try to encrypt straight from PHP, flutter never manages to decrypt. What am I missing? It shouldn't ever manage to decrypt if the algorithms are different, right?

I'm thinking the problem might be linked to block-size. Does the Encrypt module use AES-128 or AES-256?

Any insight would be appreciated. I can run some tests if need be.

Note: I tried with several different methods, ofb, cbc, ctr. I always get the same result. PHP's encryption seems to be different from Encrypt's encryption.

@leocavalcante leocavalcante added the support Questions asking about how to use the library, like StackOverflow. label Feb 11, 2021
@NTMS2017
Copy link

I got the same issue way back version 2.1.0. I found solution and add another security on top of it with the folowing.

P.S: without any loss of speed.

  1. nginx
  2. dart aqueduct
  3. php

All the encryption done in dart aqueduct server.

Dart aqueduct and php run seperate server internaly.

Used nginx as proxy and config server.

I have 2 nginx. First one is in dmz and second one behind dmz.

@TaiTair
Copy link
Author

TaiTair commented Feb 11, 2021

I got the same issue way back version 2.1.0. I found solution and add another security on top of it with the folowing.

P.S: without any loss of speed.

  1. nginx
  2. dart aqueduct
  3. php

All the encryption done in dart aqueduct server.

Dart aqueduct and php run seperate server internaly.

Used nginx as proxy and config server.

I have 2 nginx. First one is in dmz and second one behind dmz.

Thanks for the suggestion. Unfortunately changing the entire server architecture is not a solution for me.
I could potentially change what I use on the client(flutter) but for the server I am stuck with Apache and php5.6.
I just need encryption in flutter that is compatible with PHP5.6's Openssl AES encryption.

@TaiTair
Copy link
Author

TaiTair commented Feb 12, 2021

Here's what I am doing:
The message in this context is always Ping

If I try to encrypt from Flutter and decrypt from PHP:

(Flutter)

Key _secret = Key.fromUtf8("sQ&947h26s%NbK+Y");
IV _iv = IV.fromLength(16);
Dio dio = new Dio();
Encrypter enc = Encrypter(AES(_secret, mode:AESMode.ctr));
final encrypted = enc.encrypt(msg, iv: _iv);
_response = await dio.get(
    _apiUrl,
    queryParameters: {"message": Uri.encodeComponent(encrypted.base64)}
);

This sends 3EdwOMMQiFr8XNpNDJrA4A%3D%3D
Note for transmission through GET I am url encoding the base64.

(PHP)

$_SESSION['iv']=hex2bin('00000000000000000000000000000000');
$cipher = 'aes-128-ctr';
$key = base64_encode("sQ&947h26s%NbK+Y");
$msg = urldecode($msg);
$output = openssl_decrypt($msg, $cipher, $key, 0, base64_encode($_SESSION['iv']));
return base64_decode($output);

Which returns QL<@?_҅
Obviously not decrypting like the Encrypt module.
Note openssl_decrypt is set to use base64 data and return base64 data directly.

Still same IV and same key on both ends. Here's what happens if I try to encrypt from php and decrypt from flutter:

(PHP)

$_SESSION['iv']=hex2bin('00000000000000000000000000000000');
$cipher = 'aes-128-ctr';
$key = "sQ&947h26s%NbK+Y";
$encrypted = openssl_encrypt($msg, $cipher, $key, OPENSSL_RAW_DATA, $_SESSION['iv']);
$output = urlencode(base64_encode($encrypted));
echo $output;

Which returns 0psP5Q%3D%3D
Note for transmission I am url encoding the base64.
Note openssl_encrypt is set to use raw data and return raw data directly.

(Flutter)

_iv = IV.fromLength(16);
Encrypter enc = Encrypter(AES(_secret, mode: AESMode.ctr));
final decrypted = enc.decrypt64(Uri.decodeComponent(_response.data), iv: _iv);
return decrypted;

Which errors out with this:

Unhandled Exception: Invalid argument(s): Input data length must be a multiple of cipher's block size
PaddedBlockCipherImpl.process (package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart:60:9)
E/flutter ( 4607): #1      AES.decrypt (package:encrypt/src/algorithms/aes.dart:55:22)
E/flutter ( 4607): #2      Encrypter.decryptBytes (package:encrypt/src/encrypter.dart:25:17)
E/flutter ( 4607): #3      Encrypter.decrypt (package:encrypt/src/encrypter.dart:31:17)
E/flutter ( 4607): #4      Encrypter.decrypt64 (package:encrypt/src/encrypter.dart:41:12)

@leocavalcante Could you show me how to encrypt "Ping" in flutter and decrypt it correctly on the php side?
Normally openssl_encrypt uses PKCS7 like the Encrypt module. Feels like I'm missing something trivial.

@leocavalcante
Copy link
Owner

@TaiTair
I did a quick search for "php" in the repository issues. See if one of these gives you some clues:

@TaiTair
Copy link
Author

TaiTair commented Feb 12, 2021

Thanks a lot Leo.

#87 (comment) seems to work in my environment.

I'm going to use what you sent me and make it work. Thanks again.

@TaiTair
Copy link
Author

TaiTair commented Feb 13, 2021

Phew, I finally figured it out by breaking your code.
I put in my private key and my IV and then it stopped working. So it got me thinking... and I figured it was my key length that was incorrect.
Made some proper keys/ivs with php -r "echo base64_encode(openssl_random_pseudo_bytes(length));" and then used with your code everything started working.
Except for one thing: CBC worked perfectly in both directions, meaning the algorithms are identical but CTR did not. Same code, same keys, only thing I changed was the algorithm and CTR did not work at all.
Try it and see if you get the same result.

@magnuswikhog
Copy link

@TaiTair Did you try setting padding: null when creating your Encrypter instance? The default is pkcs7, which does not work with (unpadded) CTR.
I had the same problem when encrypting in AES-256-CTR in PHP and trying to decrypt in Flutter, but setting padding: null fixed it.

@OGmetamonkey
Copy link

@TaiTair "Does the Encrypt module use AES-128 or AES-256?"

Did you get an answer for this?

Also, what is the default iteration count?

@OGmetamonkey
Copy link

@TaiTair "Does the Encrypt module use AES-128 or AES-256?"

Did you get an answer for this?

Also, what is the default iteration count?

Ok, I see it uses 100 iteration count. I still don't see whether it uses s 128 or 256 bit key. Any idea?

@TaiTair
Copy link
Author

TaiTair commented Aug 23, 2021

@TaiTair "Does the Encrypt module use AES-128 or AES-256?"
Did you get an answer for this?
Also, what is the default iteration count?

Ok, I see it uses 100 iteration count. I still don't see whether it uses s 128 or 256 bit key. Any idea?

Sorry for the late reply. It's 256 bits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
support Questions asking about how to use the library, like StackOverflow.
Projects
None yet
Development

No branches or pull requests

5 participants