Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the password parameter to openssl_encrypt?

The PHP documentation for the openssl_encrypt functions states

string openssl_encrypt ( string $data , string $method , string $password [, int $options = 0 [, string $iv = "" ]] )

Can somebody help me understand what the argument named $password is? An answer could include a confirmation or rejection of the idea, that besides named $password the parameter indeed is used as the key for the encryption.

What is the password parameter to openssl_encrypt? Is it a password string (with only printable characters) or is it a key (with non-prinatable characters and ASCII-Z terminators)?


Explanation

I am stuck with the documention of PHP's openssl_encrypt. Being a nice guy and trying to do the "RTM" I cannot make much sense with the imho unsatisfying documentation.

The problem is that for me there is a difference between a password and a key when it comes to encryption. A key is directly the parameter used for encryption and hence necessarily of a specific size - "the keylength" - i.e. 128/256/512 bits depending on the cipher and keylength desired. A password on the other hand is a to my understanding a human readable string entered via the keyboard which may in difference be of any length and which is before being used to encrypt first converted into a key.

hence schematic difference:

  • password => key => encryption
  • key => encryption

Unfortunatelly in the PHP openssl_encrypt documentation I cannot find any information how to use a key. The only thing suggested is a parameter "password".

Can anybody give me a glue how a key can be used? Surely I donot want to enter the key as the password parameter as I want a specific key to be used in encryption. I do not want this key to be simply missunderstood as a parameter and serve for another key being calculated from my "key mistaken as password".

Additionally the mistery continues looking at the documention regarding the initialization vector parameter in the same openssl_encrypt function. It simply states:

iv A non-NULL Initialization Vector. and that iv should be a string. Given that the iv is normaly a binary data of a certain length and for instance a string terminating \0 (hex 0x00) can be occuring inside I am puzzled what format is desired.

In essence I feel very much left alone with the PHP documentation which also states

WARNING This function is currently not documented; only its argument list is available.

Update

I did some testing, and "trying around" to help me figure out what the password parameter is.

using this code:

$pass="0123456789abcdefghijklmnob";
$iv="0123456789abcdef";
echo "using $pass results:\n";
echo openssl_encrypt("test secret string", 'aes-128-cbc',  $pass,NULL,$iv);

I get this result:

using 0123456789abcdefghijklmnob results:
XjEeaLucY38Y6XEUceYMYKTebR4kOp3s727ipMl5KNc=

Then changing the length of the "password" parameter:

$pass="0123456789abcdefg"; //hijklmnob";
$iv="0123456789abcdef";
echo "using $pass results:\n";
echo openssl_encrypt("test secret string", 'aes-128-cbc',  $pass,NULL,$iv);

I get still the same encrypted code:

using 0123456789abcdefg results:
XjEeaLucY38Y6XEUceYMYKTebR4kOp3s727ipMl5KNc

It seems by way of testing yet not by way of being informed by the documentation that the password is indeed only considered up to the first 16 bytes which seem to be the 128 bit that would be the key.

It frightens me that in such a sensitive function (used for encryption) the documentation is bad and excessive input of one poorly documented parameter is not even warned about. Also I am quite convinced that password should rather be named key as it seems those 16 bytes do directly represent the key.

like image 990
humanityANDpeace Avatar asked Mar 17 '14 07:03

humanityANDpeace


People also ask

What is openssl_encrypt?

The openssl_encrypt() ope function can be applied for encrypting data in PHP. The syntax of openssl_encrypt() will look as follows: string openssl_encrypt( string $data, string $method, string $key, $options = 0, string $iv, string $tag= NULL, string $aad, int $tag_length = 16 )

What is IV in openssl_encrypt?

An initialization vector (IV) is an arbitrary number that can be used with a secret key for data encryption to foil cyber attacks. This number, also called a nonce (number used once), is employed only one time in any session to prevent unauthorized decryption of the message by a suspicious or malicious actor.

What is Openssl_raw_data?

OPENSSL_RAW_DATA just tells openssl_encrypt() to return the cipherText as ... raw data. By default, it returns it Base64-encoded. The source code is easy to find, but not really useful as it's not like the flag does anything extra ... The opposite - it tells PHP not to do the extra step of Base64 encoding.


1 Answers

The $password parameter is indeed the key. The key size depends on the AES mode you're using (as you know).

As you noted in your update, for AES-128, only the first 16 characters/bytes count for the key. For AES-256, it would be the first 32 characters.

When one uses the openssl_encrypt() and openssl_decrypt() functions, one can simply pass a 32 character human-readable password for the $password/key parameter.

For example, my input for the password parameter might be $password = "This is 32 characters long......";

Most people don't like having to write up a plaintext password that is a fixed length, so they might compute a hash and truncate it to the correct length. They would use this hash as their encryption key/password.

For example, I could compute an MD5 hash of a password/phrase of any length that I would like and then use that as my AES password/key:

$plaintextPass = 'This is my password. This password is not exactly 32 bytes, but that is okay because I am hashing this.';
$password = hash('md5', $plaintextPass); /* the encryption key */

With that in place, no matter what plaintext password I use, I can have a valid 32 character/byte string as my encryption key/password. This does reduce the entropy of the encryption key/password, though, because a normal 32 character string has a larger key space than an MD5 hash output (256 possibilities per byte vs. 16 possibilities per byte); however, 16^32 is still certainly out of the range of brute force.

Off topic: In some of my personal programs, I have been working on using 32 randomly generated bytes with values between 0-255. This would make the entropy of the encryption key 256^32 which is infeasible to bruteforce. This will also be resistant to dictionary attacks because the 32-bytes are randomly generated using a cryptographically secure pseudo-random number generator (CSPRNG).

So, to sum this all up, yes, the $password parameter is indeed the key used for encryption. I agree with you that is should be written as $key in the documentation, but oh well. The password/key which you select for encryption can be humanly readable as long as it satisfies the length requirements of the hashing key. To satisfy these length requirements, one can hash a human-readable/plaintext password and use the hash of that password as the key ($password parameter), but the human-readable password should still be long and unique.

The documentation is not very clear, however this comment on the openssl_encrypt() PHP doc page really helped me when I was trying to understand the function. The comment provides an example as well as useful information. To direct quote the author of the comment:

Because the password parameter documented here is not the password. ... It is the key! [Comment minorly edited]

like image 162
Spencer D Avatar answered Sep 25 '22 00:09

Spencer D