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 = '&>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+*/-'.?
)?