How to Encrypt Database with Laravel

From WikiHTP

In some occasions, we may have the need to encrypt databases with Laravel, even more so with the arrival of the RGPD, if that is your case, in this tutorial we will see how easy it is to achieve this purpose thanks to Eloquent Mutators and Accessors.

Define a Trait to extend Eloquent[edit]

The first thing we are going to do to achieve a more dynamic behaviour is to create a trait to overwrite Eloquent's getAttribute and setAttribute methods, which will allow us to alter the data of our model when obtaining and establishing data.

<?php

namespace App\Traits;

/**
 * Trait Encryptable
 * @package App\Traits
 */
trait Encryptable
{
  
    /**
     * @return mixed
     */
    public function getSecretKey () {
        return env('APP_DB_KEY');
    }

    /**
     * @return mixed
     */
    public function getKeyInitVector () {
        return env('APP_KEY');
    }

    /**
     * @return \Illuminate\Config\Repository|mixed
     */
    public function getEncryptMethod () {
        return config('app.cipher');
    }

    /**
     * @param $string
     * @return bool|string
     */
    public function encrypt( $string ) {
        $key = hash( config('app.encryption'), $this->getSecretKey() );
        $iv = substr( hash( config('app.encryption'), $this->getKeyInitVector() ), 0, 16 );
        return base64_encode( openssl_encrypt( $string, $this->getEncryptMethod(), $key, 0, $iv ) );
    }

    /**
     * @param $string
     * @return bool|string
     */
    public function decrypt( $string ) {
        $key = hash( config('app.encryption'), $this->getSecretKey() );
        $iv = substr( hash( config('app.encryption'), $this->getKeyInitVector() ), 0, 16 );
        return openssl_decrypt( base64_decode( $string ), $this->getEncryptMethod(), $key, 0, $iv );
    }

    /**
     * @param $key
     * @return bool|string
     */
    public function getAttribute($key)
    {
        if (in_array($key, $this->encryptable)) {
            $value = $this->decrypt($value);
            return $value;
        }
        return parent::getAttribute($key);
    }

    /**
     * @param $key
     * @param $value
     * @return mixed
     */
    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->encryptable)) {
            $value = $this->encrypt($value);
        }
        return parent::setAttribute($key, $value);
    }
}

In addition to the methods mentioned above, we also have 2 important methods, the encrypt method and the decrypt method, it is important to say that this type of encryption is not reliable if the data you want to manage is sensitive, the reason is that we are going to want to encrypt but also decrypt to show these data later, even to log in using email, the latter is the real reason, to make sure the variable $iv should be dynamic and not static.

Apply the Trait Encryptable to our models[edit]

Now let's open for example the User model to use the Trait Encryptable in the following way.

<?php

namespace App;

use App\Traits\Encryptable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

/**
 * App\User
 */
class User extends Authenticatable
{
    use Notifiable, Encryptable;

    /**
     * @var array
     */
    protected $encryptable = [
        'name', 'email',
    ];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

Only by using the $encryptable property passing the columns that we want to encrypt in the database we have enough, if now, for example, you register a new user you will see that the name and email columns are encrypted in database and if you get the users you will see that when you access these columns appear unencrypted.

About This Tutorial

This page was last edited on 14 February 2019, at 22:22.