0

I have come accross other threads with similar questions but due to recent changes in PHP (ie. mcrypt removal), I am seeking some advice as to how I'd best go about this using OpenSSL in 2017/18.

Using echo 'this string will be encrypted' | openssl enc -aes-256-cbc -a -pass pass:123 in the Mac Terminal, I was able to password encrypt the string and would now like to pass this (as a parameter) into a server-side PHP function to decrypt.

Having studied this question, I can see that it is possible but it uses the now removed mcrypt function. Further reading in the PHP manual, I am no closer to figuring out how to reverse this encryption command into its PHP decryption equivalent.

This recent answer is what I have implemented so far, yet again, it just won't work with a Terminal generated encryption, only one which was created in PHP (not shown here).

<?php
  $encrypted_string = $_GET['data'];
  $password = '123';
  $decrypted_data = openssl_decrypt($encrypted_string, "AES-256-CBC", $password);
  print "Decrypted Data: <$decrypted_data>\n";
?>

The OpenSSL PHP manual states that either plain text or base64 encoded strings can be passed in and be decrypted. As I have used the -a flag during encryption, I would expect base64 to be passed in, thus eliminating the source as a potential reason why no decrypted data is returned.

I have taken care of URL encoding such that any + symbols produced by the encryption algorithm are replaced with their - %2B - URL-Safe equivalent as they would otherwise be turned into a space character, thus breaking the parameter string. This further ensures that the encoded input string is correctly addressed by the decryption algorithm.

Questions: Why won't my PHP function decrypt the string generated by the terminal command, although both use the same method and password? What is missing from my PHP code that would enable this to work?

Cheers everyone.

UPDATE

I am now using Terminal command:
echo 'blah' | openssl enc -aes-256-cbc -a -K B374A26A71490437AA024E4FADD5B497FDFF1A8EA6FF12F6FB65AF2720B59CCF -iv 64299685b2cc8da5 which encrypts to: Y4xelTtEJPUHytB5ARwUHQ==

I pass this to PHP using www.example.com/?data=Y4xelTtEJPUHytB5ARwUHQ==

PHP should take data param and decrypt. Currently, that function looks like this:

<?php
$encrypted_string = base64_decode($_GET['data']);
$key = 'B374A26A71490437AA024E4FADD5B497FDFF1A8EA6FF12F6FB65AF2720B59CCF';
$iv = '64299685b2cc8da5';

$output = openssl_decrypt($encrypted_string, 'AES-256-CBC', hex2bin($key), OPENSSL_RAW_DATA, hex2bin($iv));
print "Decrypted Data: <$output>\n";
?>
ProGrammer
  • 976
  • 2
  • 10
  • 27
  • 3
    Recall that AES only operates on specific key sizes. You encrypt using AES-256 and only pass a 24 bit key ("123"). This is possible because OpenSSL uses a KDF to derive a key of acceptable length from this password. The `openssl_decrypt` function does **not** do this, so by passing `123` as the key you are already invoking an undefined behavior. You should determine what the KDF used by OpenSSL is and replicate this in your PHP code. – Luke Joshua Park Dec 09 '17 at 12:55
  • @LukePark I have tried various lengths of values and functions all weekend long. Including changing the number of characters in the key. Yet, I don't understand why the OpenSSL from Terminal is not compatible with the OpenSSL decryption commands in PHP. Would someone be able to give a code example that is relevant to the context of my question? I can en/decrypt in Terminal and PHP separately but not somehow not encrypt in one language and decrypt in the other. Any help is really appreciated. – ProGrammer Dec 11 '17 at 06:45
  • Did you read my response or...? Did you do what I said you need to do? The KDF is what is important. – Luke Joshua Park Dec 11 '17 at 06:49

1 Answers1

1

OpenSSL uses a proprietary KDF that you probably don't want to put the effort in to reproduce in PHP code. However, you can pass your key as pure hex instead, avoiding the KDF, by using the -K flag:

echo 'blah' | openssl enc -aes-256-cbc -K 0000000000000000000000000000000000000000000000000000000000000000

Here, the large hex string is your 256-bit key, hex encoded. This encryption operation will be compatible with your PHP.

Luke Joshua Park
  • 9,527
  • 5
  • 27
  • 44
  • Thank you for the clarification. In order to get the URL-friendly string, I have added the `-a` flag behind the method like in my original post. Running the above from Terminal returns `iv undefined` so I added `-iv` to the end, along with another value, but PHP says: `Warning: openssl_decrypt: IV passed is 32 bytes long which is longer than the 16 expected by selected cipher...` makes sense in plain English so I took 1/2 off and started with the encryption again (this time using only half the amount of characters in the `-iv` parameter). No luck decrypting it on the other side. – ProGrammer Dec 11 '17 at 08:10
  • @ProGrammer Did you use the IV in the PHP code too? – Luke Joshua Park Dec 11 '17 at 08:49
  • @ProGrammer IV should be 16 bytes not 8. You also aren't base64 deciding the ciphertext in your PHP.. – Luke Joshua Park Dec 11 '17 at 09:28
  • @ProGrammer It's hex encoded... Two characters per byte, so there is only 8 bytes of IV. Double the length... – Luke Joshua Park Dec 11 '17 at 10:18
  • I managed to get the decryption part working by including the `hex2bin()` function in the `$output` line. Thank you. I now want to change direction: https://stackoverflow.com/questions/47768006/decrypting-a-php-generateed-openssl-string-in-terminal perhaps that is something you may be interested in assisting me with. Thanks again. – ProGrammer Dec 12 '17 at 08:25