encrypt
encrypt copied to clipboard
Compatibility with PHP5.6's openssl AES
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.
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.
- nginx
- dart aqueduct
- 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.
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.
- nginx
- dart aqueduct
- 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.
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.
@TaiTair I did a quick search for "php" in the repository issues. See if one of these gives you some clues:
- https://github.com/leocavalcante/encrypt/issues/42#issuecomment-495820762
- https://github.com/leocavalcante/encrypt/issues/69#issuecomment-526865580
- https://github.com/leocavalcante/encrypt/issues/87#issuecomment-549619391
Thanks a lot Leo.
https://github.com/leocavalcante/encrypt/issues/87#issuecomment-549619391 seems to work in my environment.
I'm going to use what you sent me and make it work. Thanks again.
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.
@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.
@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?
@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 "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.