Encrypting Laravel Eloquent models with CipherSweet

July 1st, 2022

In your project, you might store some sensitive personal or credential data in your database. Should an unauthorised person get access to your DB, all this sensitive can be read.

To solve this problem, you can encrypt the data. This way, unauthorised persons cannot read it, but your application can still decrypt it when you need to display or work with the data.

CipherSweet is a backend library developed by Paragon Initiative Enterprises for implementing searchable field-level encryption. It can encrypt and decrypt values in a very secure way. It is also able to create blind indexes. A blind index can be used to perform some targeted searches on the encrypted data. The indexes themselves are unreadable by humans.

We've just released laravel-ciphersweet. This package is a wrapper over CipherSweet, which allows you to easily use it with Laravel's Eloquent models.

Preparing your model and choosing the attributes that should be encrypted

Add the CipherSweetEncrypted interface and UsesCipherSweet trait to the model that you want to add encrypted fields to.

You'll need to implement the configureCipherSweet method to configure CipherSweet.

use Spatie\LaravelCipherSweet\Contracts\CipherSweetEncrypted;
use Spatie\LaravelCipherSweet\Concerns\UsesCipherSweet;
use ParagonIE\CipherSweet\EncryptedRow;
use Illuminate\Database\Eloquent\Model;

class User extends Model implements CipherSweetEncrypted
{
    use UsesCipherSweet;
    
    public static function configureCipherSweet(EncryptedRow $encryptedRow): void
    {
        $encryptedRow
            ->addField('email')
            ->addBlindIndex('email', new BlindIndex('email_index'));
    }
}

Generating an encryption key

We've also added a small helper command to the package that allows you to generate a new key in a way that is suggested by Paragon Initiative Enterprises.

This encryption key is used to encrypt your values.

php artisan ciphersweet:generate-key

Encrypting model attributes

Once everything is set up, you can start encrypting your model values:

php artisan ciphersweet:encrypt <your-model-class> <generated-key>

The command will update all the encrypted fields and blind indexes of the model.

If you have a lot of rows, this process can take a long time since encryption is a resource intensive operation. Don't worry if it times out for some reason, the command is always restartable and only tries to encrypt models when it's needed.

Updating your .env file

After the fields have been encrypted, you should add the generated CipherSweet key to your .env file.

CIPHERSWEET_KEY=<YOUR-KEY>

The key will be used by your application to read encrypted values.

Searching on blind indexes

Even though values are encrypted, you can still search them using a blind index. The blind indexes will have been built up when you ran the command to encrypt the model values.

Our package provides a whereBlind and orWhereBlind scope to search on blind indexes.

The first parameter is the column, the second the index name you set up when calling ->addBlindIndex, the third is the raw value, the package will automatically apply any transformations and hash the value to search on the blind index.

$user = User::whereBlind('email', 'email_index', '[email protected]');

In closing

CipherSweet is a very powerful library, and our package makes it very approachable. Of course, be very sure about what columns actually need encrypting, and don't overdo it, encryption is resource intensive and comes with some downsides.

We'll be using this package sparingly in the development of our upcoming SaaS mailcoach.cloud to protect the personal information that will be stored by our users.

Of course, laravel-ciphersweet isn't the first package that our team has built. On our company website, check out all of our open source packages in this long list. If you want to support us, consider picking up any of our paid products.

MENU