php - Encryption/decryption of strings and files using mcrypt

1k Views Asked by At

From time to time I come around the task of creating functions for encrypting/decrypting strings and files in PHP. I decided to finally nail those functions and did some searching but I couldn't find enough resources to confirm the security of these functions.

Please note that I don't want to use another full-blown library unless necessary and I don't see why PHP provides OpenSSL & mcrypt functions but nobody really implements them.

I was able to find these functions but they are not commented and some steps were unclear (also they do not generate a key but use a predefined one). Following these functions I also found this stackoverflow question but the first answer uses another library while the second one uses ECB.

edit: I updated the code sample which previously utilized mcrypt to using only OpenSSL as suggested in the comments:

function generate_key($cipher = 'AES-256-CBC')
{
    return base64_encode(openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher))); // Generate a random key - currently using the function for the vector length
}
function encrypt($data, $key, $cipher = 'AES-256-CBC')
{
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher)); // Generate a random initialization vector
    return base64_encode($iv) . '$' . openssl_encrypt($data, $cipher, base64_decode($key), false, $iv); // Return a base64 encoded string containing the iv and the encrypted data
}
function decrypt($data, $key, $cipher = 'AES-256-CBC')
{
    $data = explode('$', $data); // Explode the previously encoded string

    if(count($data) == 2)
        return openssl_decrypt($data[1], $cipher, base64_decode($key), false, base64_decode($data[0])); // Decrypt the data given key and the iv
    else
        return false;
}

I tested encryption and decryption using these function like this:

$input = 'Hello world!';
echo 'Original data: ' . $input . '<br /><br />';

$key = generate_key();
$encrypted = encrypt($input, $key);
echo 'Key used for encryption: ' . $key . '<br />';
echo 'Encrypted data: ' . $encrypted . '<br /><br />';

$decrypted = decrypt($encrypted, $key);
echo 'Decrypted data: ' . $decrypted . '<br />';

The question: Is OpenSSL properly implemented as shown above? Can they be used for files too?

These are the old functions using mcrypt. Don't use them anymore.

function generate_key($cipher = MCRYPT_RIJNDAEL_256)
{
    return bin2hex(openssl_random_pseudo_bytes(mcrypt_get_key_size($cipher, MCRYPT_MODE_CBC))); // Generate a random key using OpenSSL with size given from mcrypt depending on cipher
}
function encrypt($data, $key, $cipher = MCRYPT_RIJNDAEL_256)
{
    $iv = mcrypt_create_iv(mcrypt_get_iv_size($cipher, MCRYPT_MODE_CBC)); // Generate random initialization vector with size given from mcrypt depending on cipher
    return bin2hex($iv) . '$' . bin2hex(mcrypt_encrypt($cipher, pack('H*', $key), $data, MCRYPT_MODE_CBC, $iv)); // Return the initialization vector and encrypted data as ASCII string
}
function decrypt($data, $key, $cipher = MCRYPT_RIJNDAEL_256)
{
    $data = explode('$', $data); // Split the input data by $ to retrieve the initialization vector and the encrypted data

    if(count($data) == 2) // Check if there are 2 parts after splitting by $
        return mcrypt_decrypt($cipher, pack('H*', $key), pack('H*', $data[1]), MCRYPT_MODE_CBC, pack('H*', $data[0])); // Return the decrypted string
    else
        return false; // Return false if the given data was not properly formatted (no $)
}
1

There are 1 best solutions below

10
On

Current best practise is to avoid using mcrypt in favor of openssl.

And the speed benchmark, where openssl is pretty much faster.