1

Is there a definied keysize to be used with the "AES_256-CBC" method in PHP, and what is the size?

Some background:

I want to store encrypted text into a PostgreSQL database. The user who posts the data has a key (stored in db) which gets appended to a generic private key hard coded in the library.

$key = $genericKey . $userKey;

The used encryption method is "AES-256-CBC" with an iv_size of 16. The IV gets prepended to the encrypted string

$return = $iv.$encrypted

This is then stored in the database.

It appears that if I produce an extremely large generic key, then store some data with $userkey1, and then decrypt it with $userkey2, the data just gets decoded. If I rerun it with a small generic key and small user key, it does not get decoded. To me, it looks as if the big key gets truncated somehow.

Could someone confirm this and tell me what the max keysize is? What is the best-practice to make sure the set key doesn't exceed the key_size* E.g.: md5($key) because this produces a "fixed" amount of characters.

update

Because apparently php has its own implementation of the AES, this is the way I implement it in my own Class:

class Crypto {

function __construct(){
  $this->iv_size = 16;
  $this->sleutel = 'somelongkey';
  $this->encryptionMethod  = 'AES-256-CBC';
}

    private function encrypt($str){
 $sleutel = $this->sleutel . $this->userKey;
 $iv = $this->generateRandomString($this->iv_size);
 $cipher = openssl_encrypt($str, $this->encryptionMethod, $sleutel, 0, $iv);
 return $iv.$cipher;
    }
    public function decrypt($data){
        $iv = substr($data, 0, $this->iv_size);
 $sleutel = $this->sleutel . $this->userKey;

        return openssl_decrypt(substr($data, $this->iv_size), $this->encryptionMethod, $sleutel, 0, $iv);

    }
}
stUrb
  • 113
  • 1
  • 5

1 Answers1

2

You're simply appending the userKey to your "sleutel" (aka key) in this piece of code:

$sleutel = $this->sleutel . $this->userKey;

Problem is, doing that can result in $sleutel lengths beyond the expect 256 bits (32 bytes), or - as you are experiencing - less than the expected 256 bits (32 bytes/characters).

As @CodesInChaos correctly mentioned in his comment:

AES-256 uses a 256 bit or 32 byte key by definition. No more, no less.

So, to fix your problem, you will have to make sure the key you are passing to your cipher function is no more and no less than 32 bytes.

To achieve that, you can simply choose to follow the usual path of encryption by taking your $sleutel and hash your key to the expected 256-bit length with (for example) MD5, like this:

$sleutel = md5($this->sleutel . $this->userKey);

or — if you prefer to choose another hash and a speedier function — you can use PHP's hash function, with it's multiple of available hashes to select from, like (for example) this:

$sleutel = hash('ripemd128', $this->sleutel . $this->userKey);

But… that's not the way I would recommend you to do it! Because, you don't want to use a weak hash like MD5 (which is known to have collisions), and you surely don't want to feed a weak hexadecimal character sequence to your cipher either, do you?

My Recommendation

Following current crypto standards, my recommendation is to use SHA256 the way it is supposed to be used in this case:

$sleutel = hash('sha256', $this->sleutel . $this->userKey, TRUE);

Notice that there's a 3rd parameter which is set to TRUE, which means $sleutel will contain 32 raw bytes (= binary characters) instead of 64 human-readable hexadecimal characters.

I'm sure that will fix your "short-key" related problems, as well as any potential "long-key" problems.

Mike Edward Moras
  • 18,161
  • 12
  • 87
  • 240