Encrypting an image in PHP
So you’ve got an image, encoded into Base64 that you need to encrypt.
In PHP it’s a straightforward task. Here’s a short guide to create a PHP class that will encrypt an image.
Assumptions
Your image has already been encoded into Base64. It is likely that image string sent to your server arrived via a POST request, Base64 encoded.
First, we create an image encryption class:
Class imageEncryption {
public function __construct($inputString, $passphrase) {
$this->inputString = $inputString;
$this->passphrase = $passphrase;
}
Above, we have named our class imageEncryption and created a constructor. When this class is instantiated, it requires two input variables:
- $inputString. The string of the Base64 encoded image data, to be encrypted.
- $passphrase. This is the passphrase that will be used to encrypt the image. Where this comes from and what it is, I will let the reader decide.
Next, we write the function that will perform the encryption:
public function encryptImage() : string {
$requiredIvLength = openssl_cipher_iv_length($cipher="aes-256-ofb");
$iv = openssl_random_pseudo_bytes($requiredIvLength);
$cipher = 'aes-256-ofb';
$encryptedString = openssl_encrypt($this->inputString, $cipher, OPENSSL_RAW_DATA, $iv);
$encryptedImage = $iv . $encryptedString;
return $encryptedImage;
}
It seems short doesn’t it? The PHP language contains functions which can safely encrypt data. Let’s break this function down.
public function encryptImage() : string {}
Above we define our function name and set the return data type; a string. Simple stuff.
public function encryptImage() : string {
$requiredIvLength = openssl_cipher_iv_length($cipher="aes-256-ofb");
$iv = openssl_random_pseudo_bytes($requiredIvLength);
$cipher = 'aes-256-ofb';
$encryptedString = openssl_encrypt($this->inputString, $cipher, OPENSSL_RAW_DATA, $iv);
$encryptedImage = $iv . $encryptedString;
return $encryptedImage;
}
This is where things get become complex. We’re using built-in PHP functions with flags, plus some terminology we might not be familiar with.
Here’s an outline of what is happening and why:
- Set the variable $requiredIvLength as a function of the aes-256-ofb cipher. The PHP function openssl_cipher_iv_length creates an initialisation vector which is compatible with our desired encryption type. What is an initialisation vector? All encryption relies on randomisation to use as a factorial in the encryption algorithm’s large-prime number mathematics. The ‘initialisation vector’ sets the correct length (in bytes) of randomisation for the encryption function we are going to use.
- Set the variable $iv as a function of the $requiredIvLength. This function creates the random bytes that we need, set to the length produced by the $requiredIvLength variable. This is a useful php function providing us with the correct initialisation vector length for different encryption algorithms.
- Set the variable $cipher as a string. In our case, we are using the aes-256-ofb encryption algorithm. To see a full list of available encryption algorithms you can run:
echo '<pre>';
echo var_dump(openssl_get_cipher_methods());
echo '<pre>';
- The openssl_encrypt function takes 4 variables. This is the function which encrypts our data. These four variables are:
- The string data to be encrypted
- The encryption cipher we previously assigned to the $cipher variable
- The default behaviour for the openssl_encrypt function is to convert the input string to Base64 prior to encryption. Since our string is already Base64, the flag OPENSSL_RAW_DATA ensures that the data is not converted and is unchanged
- $iv this gives the openssl_encrypt function the random bytes it needs to safely encrypt the data
- $encryptedImage = $iv . $encryptedString; is probably the most unusual function, why do we concatenate the $iv with the encrypted string? This is so that when we come to decrypt our image, we can retrieve the same $iv required to perform the decryption. Without the initialisation vector it is simply impossible to decrypt the data.
- The final line returns the encrypted data variable
That’s it! Oh wait. No, we need a function to decrypt our image. We can do this by writing a function that is almost the reverse of the encryption function.
The difference with the decryption function, is that we can hard code some assumptions, since we know the way that the original data was encrypted.
Here is our decryption function. It should seem quite self explanatory when examined in the context of the encryption function:
public function decryptImage($inputString) : string {
$encryptedImage = $inputString;
$iv = substr($encryptedImage, 0, 16);
$encryptedImage = substr($encryptedImage, 16);
$decryptedImage = openssl_decrypt($encryptedImage, 'aes-256-ofb', $this->passphrase, OPENSSL_RAW_DATA, $iv);
return $decryptedImage;
}
You can see here that we extract the initialisation vector and the encrypted data from the $inputString, using the substr function. The function openssl_decrypt requires the initialisation vector as a parameter in the same way that the openssl_encrypt function does. You also need to supply the passphrase which was used to encrypt the data originally.
Thomas