These days security online is kind of a big deal. Major hacking stories are becoming a monthly event. The recent Ashely Madison hack is an example of security failures on a lot of different levels. Now its difficult to know for sure since there are rumours that it was an inside job. And Inside jobs are kind of hard to protect against. But that doesn’t mean you can’t improve security.

People talk a lot about storing passwords as plain text in the database as being a big no no. And it is for sure. But what about the other data? Emails. Phone numbers. Other personal info.

I am currently working on a medical related app and in Ontario, there are pretty strict regulations regarding how you store medical information online. I had been struggling with this for a few days. Then as usual, Laravel presented the solution. Using a Trait to encrypt fields on I/O. So here is how to do it.

First lets create the Trait itself. The Trait sort of intercepts reading from and writing to the database. It looks to see whether you have asked that a certain parameter to be encrypted, and if so Encrypts it on the way in and Decrypts it on the way out. I store Traits in app/Traits but you can store them wherever you want as long as you namespace it accordingly.

app/Traits/EncryptableTrait.php


namespace App\Traits;

use Illuminate\Support\Facades\Crypt;

trait EncryptableTrait {

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

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

        return $value;
    }

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

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

So in the above example I have told my User model to use the EncryptableTrait on the name, phone and email fields. Now when I create or save a user, the fields are encrypted using the built-in Crypt package. And thats it!

Here is the user data table unencrypted:
users_unencrypted

 

And here is the data encrypted

Screen Shot 2015-08-26 at 4.15.53 PM

 

Which one would you rather your hacker have access to? But what is really going on here?

Your app key and whats happening behind the scenes

I am not even going to dive all the way in to how the Crypt feature in Laravel works. But I will tell you a major part of the encrypting process is made possible using the random key that Laravel generates. You will find this in your .env file under APP_KEY. So it is pretty important to keep this key safe and away from evil.

But there is something else. If you lose this key, and for some reason your application explodes and you can no longer recover it, you will not be able to decrypt your data. The key is required to read any data that was encrypted with said key. Thats why you may notice that if you regenerate the key, your passwords on the app will no longer work. This is because when the user registered the password was encrypted with the then current app key.

So this means if you have an application where the main data must be encrypted, you need to have an organized was of managing the app key, and a process for changing the key if necessary. This may involve keeping the key backed up offline somewhere. It will also require a process for changing the key. Remember if you simply change your app key, none of the data will be readable and everything will break. So the process of changing a key if necessary might be to write a script that can decrypt the entire database against the old key, generate a new key, then re-encrypt the entire database with the new key.

Its a bit scary I know. If anyone has experience with this by all means chime in below.