PHP AES-256 CBC faster than AES-128 CBC? For the last couple of days, I have been learning a bit about encrypting data in PHP, as I need a good encryption/decryption function for storing users' passwords in a DB. I use openssl_random_pseudo_bytes() for the IV, hash_hmac with SHA256 and openssl_encrypt(). Here's the function for encryption:

// 32 bytes (256-bit) (64 char) encryption key
define('ENCRYPTION_KEY', 'd027e7*+7b6d5fcd55f4b5c32611b87cd923e88837b63bf2941ef819dc8ca282');
// 16 bytes (128-bit) (32 char) encryption key
define('ENCRYPTION_KEY2', 'b6d5fcd55f4b5c32611b87cd923e88ae');
function pw_encrypt($encrypt, $key, $type){

    $hmac_key = 'd027e7*+7b6d5fcd55f4b57su921b87cd923e88837b63bf2941ef819dc8ca282';

    $encrypt = serialize($encrypt);

    $method = "AES-$type-CBC";

    $isCryptoStrong = false; // Will be set to true by the function if the algorithm used was cryptographically secure
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method), $isCryptoStrong);

    if(!$isCryptoStrong)
        throw new Exception("Non-cryptographically strong algorithm used for iv generation. This IV is not safe to use.");

    $mac = hash_hmac('sha256', $encrypt, $hmac_key);

    $passcrypt = openssl_encrypt($encrypt.$mac,$method,$key,OPENSSL_RAW_DATA,$iv);
    $encoded = base64_encode($passcrypt).'|'.base64_encode($iv);

    return $encoded;
}


So I've run this bit of code to test AES-128/-256 with 128 bit / 256 bit encryption keys. Now the thing that bothers me that AES-256 seems faster than AES-128, is that normal?

Here are the results-- times are usually something similar to this:

$data = '&amp;&gt;tsX@(3BjsAepZW';
Encrypted Data AES-128 128bit key: Length: 153 Total Execution Time: 2.6027361551921E-6 Mins
Encrypted Data AES-128 256bit key: Length: 153 Total Execution Time: 1.8000602722168E-6 Mins
Encrypted Data AES-256 128bit key: Length: 153 Total Execution Time: 1.7166137695313E-6 Mins
Encrypted Data AES-256 256bit key: Length: 153 Total Execution Time: 1.7166137695313E-6 Mins


So, what bugs me:


Am I doing something wrong here, or is AES-128 really slower than AES-256?
How come the length of encoded string is in all 4 cases the same?
Does the encryption key have to be in HEX format or can I use *+/-_.,'?
The key for has_hmac, should it be randomly generated or just as I have it, predefined? If random, what's the best pratice for creating a random key? And what length and type should it be (hex or +*/-'.?)?
I'll answer in order:


No, you may not be doing something wrong. This is just the compiler warming up and performing optimizations. The second run you see that AES-128 is already about as fast, which is what you would expect (it should be ever so slightly faster in the end, but that might not even be noticeable).
Don't know, you'd have to debug, because that's certainly wrong.
The key should not be in any kind of encoding. The key used by OpenSSL should consist of bytes indistinguishable from random. You can use hexadecimals for storing keys in string (something that's rather questionable as well) but you should decode it before using it. 
Same as for the encryption key; you'd use openssl_random_pseudo_bytes or another secure random number generator. Then you may encode it to hexadecimals or base 64, as long as you decode it again to binary before you use it.


Note that if you provide a 16 byte key as 32 hexadecimals that you might be using AES-256 without realizing it yourself. Best test against another framework / crypto library (but NOT mcrypt).



You should not store your users passwords encrypted. Instead you should use a password hash such as bcrypt.