1
$\begingroup$

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);

    }
}
$\endgroup$
2
  • 2
    $\begingroup$ AES-256 uses a 256 bit or 32 byte key by definition. No more, no less. $\endgroup$ Commented Oct 11, 2013 at 11:48
  • $\begingroup$ Since PHP does not have native AES crypto support, you're either using a module or library. To be sure we're all talking about the same thing, it would be cool if you could mention if you are using Mcrypt, some other module, or maybe even a PHP class or library? (Because sometimes, the devil hides in the details.) $\endgroup$
    – e-sushi
    Commented Oct 11, 2013 at 12:13

1 Answer 1

2
$\begingroup$

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.

$\endgroup$
4
  • $\begingroup$ Wow. Thank you e-sushi for this elaborate answer! Am I correct that with your recommended solution I always will produce a correct size key, no matter the size of $this-sleutel.$this->userKey ? $\endgroup$
    – stUrb
    Commented Oct 11, 2013 at 15:37
  • $\begingroup$ @stUrb Absolutely correct. That's one of many reasons why I recommended it… ;) As noted, remember to set that 3rd parameter to TRUE to be sure you get binary instead of hex characters in your $sleutel. (Btw.: Vlaams of Nederlands? In ieder geval, graag gedaan!) $\endgroup$
    – e-sushi
    Commented Oct 11, 2013 at 15:40
  • 1
    $\begingroup$ For password based keys derivation (i.e. where the input entropy is significantly below your key size), you should better use a slow hash function instead of any fast one like SHA-256. $\endgroup$ Commented Oct 18, 2013 at 19:47
  • $\begingroup$ @PaŭloEbermann Valid point. But I have good hopes OP discovered the different hash-types PHP offers in that functions. ;) $\endgroup$
    – e-sushi
    Commented Oct 18, 2013 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.