Encrypting Laravel Models

With the recent WikiLeaks dump regarding the CIA, something has became quite apparent. That is, Encryption works. Now, encrypting data in Laravel can be made really easy with some modifications to your Model file so why aren’t we all doing that?

One small precursor that I would advise everyone to do first is to enable SSL on your website. It is super simple and free if you have access to use LetsEncrypt and if not it would be worthwhile paying for a Certificate through your host (or moving hosts!!)

Ok, so let’s move onto how we can make encrypting Laravel model data super simple! There will be a link to a demo project which you use at the end of this post so feel free to clone that down and have a good look for yourself.

Firstly, we need to think about where we want to perform the logic. So we don’t want to be doing it in the controller, we will likely have to access the same data throughout different parts of our App. This in mind, I would want it to occur at a model level.

With this, as soon as data is being retrieved or set we will perform the necessary functions to mutate the data into it’s appropriate state. But, we have multiple models in our application. So we need to think about reusability, to keep it DRY we could use a Trait which is controlled via a simple array of parameters that we store in the actual model.

Let’s look at some Code, firstly our Trait:

trait Encryptable
{
    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);

        if (in_array($key, $this->encryptable)) {
            $value = Crypt::decrypt($value);
        }
    }

    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->encryptable)) {
            $value = Crypt::encrypt($value);
        }

        return parent::setAttribute($key, $value);
    }
}

For this Trait we are wanting to hook into the getAttribute and setAttribute functions that are part of the default model architecture and override them to perform Crypt actions if the column is part of the encryptable array.

Let’s take a look at our model now to checkout that encryptable array:

class Patient extends Model
{
    use Encryptable;

    protected $encryptable = [
        'blood_type',
        'medical_conditions',
        'allergies',
        'emergency_contact_id',
    ];
}

As you can see we have a Model called Patient. We have told this Model to use the Encryptable trait which we have just defined and finally we are setting the $encryptable array (which our Trait will rely on)

With the above, when the get or set functions are called on the Patient model we will be Encrypting and Decrypting the following columns: ‘blood_type’ ‘medical_conditions’ ‘allergies’ and ‘emergency_contact_id’

The rest of the columns in that model will be ignored and stored as plain text.

Make sense? I hope so, anyway here’s a link to my demo project on Github: https://github.com/domtalbot/Laravel-Encrypted

If you have liked this post and see the benefits, why not give it a share so that everyone can start utilising this method!

Original credit for the Encryptable trait goes to the author in this Laracasts comment: https://laracasts.com/discuss/channels/laravel/encrypting-model-data