Giter VIP home page Giter VIP logo

austinheap / laravel-database-encryption Goto Github PK

View Code? Open in Web Editor NEW
247.0 15.0 74.0 1.31 MB

A package for automatically encrypting and decrypting Eloquent attributes in Laravel 5.5+, based on configuration settings.

Home Page: https://packagist.org/packages/austinheap/laravel-database-encryption

License: MIT License

PHP 97.86% TSQL 2.14%
laravel laravel5 laravel-5-package database databases encryption encrypt decryption decrypt aes

laravel-database-encryption's Introduction

Laravel 5.5+ Database Encryption Package

laravel-database-encryption banner from the documentation

License Current Release Total Downloads Build Status Scrutinizer CI StyleCI Maintainability Test Coverage

A package for automatically encrypting and decrypting Eloquent attributes in Laravel 5.5+, based on configuration settings.

The purpose of this project is to create a set-it-and-forget-it package that can be installed without much effort to encrypt and decrypt Eloquent model attributes stored in your database tables, transparently. It is therefore highly opinionated but built for configuration.

When enabled, it automagically begins encrypting data as it is stored in the model attributes and decrypting data as it is recalled from the model attributes.

All data that is encrypted is prefixed with a header so that encrypted data can be easily identified, encryption keys rotated, and (optionally) versioning of the encrypted data format itself.

This supports columns that store either encrypted or non-encrypted data to make migration easier. Data can be read from columns correctly regardless of whether it is encrypted or not but will be automatically encrypted when it is saved back into those columns. Standard Laravel Eloquent features like attribute casting will continue to work as normal, even if the underlying values stored in the database are encrypted by this package.

There is documentation for laravel-database-encryption online, the source of which is in the docs/ directory. The most logical place to start are the docs for the HasEncryptedAttributes trait.

Table of Contents

Requirements

Status

Framework Version Release Status PHP v7.1 PHP v7.2 PHP v7.3
Laravel v5.5 v0.1.0 (Packagist) Stable Build Status Build Status Build Status
Laravel v5.6 v0.1.1 (Packagist) Stable Build Status Build Status Build Status
Laravel v5.7 v0.2.0 (Packagist) Stable Build Status Build Status Build Status
Laravel v5.8 v0.2.1 (Packagist) Stable Build Status Build Status Build Status

Schemas

Encrypted values are usually longer than plain text values, sometimes much longer. You may find that the column widths in your database tables need to be altered to store the encrypted values generated by this package.

If you are encrypting long strings such as JSON blobs then the encrypted values may be longer than a VARCHAR field can support, and you will need to alter your column types to TEXT or LONGTEXT.

The FAQ contains migration instructions if you are moving from elocryptfive.

Installation

Step 1: Composer

Via Composer command line:

$ composer require austinheap/laravel-database-encryption

Or add the package to your composer.json:

{
    "require": {
        "austinheap/laravel-database-encryption": "^0.2"
    }
}

Step 2: Enable the package (Optional)

This package implements Laravel auto-discovery feature. After you install it the package provider and facade are added automatically.

If you would like to declare the provider and/or alias explicitly, you may do so by first adding the service provider to your config/app.php file:

'providers' => [
    //
    AustinHeap\Database\Encryption\EncryptionServiceProvider::class,
];

And then add the alias to your config/app.php file:

'aliases' => [
    //
    'DatabaseEncryption' => AustinHeap\Database\EncryptionFacade::class,
];

Step 3: Configure the package

Publish the package config file:

$ php artisan vendor:publish --provider="AustinHeap\Database\Encryption\EncryptionServiceProvider"

You may now enable automagic encryption and decryption of Eloquent models by editing the config/database-encryption.php file:

return [
    'enabled' => env('DB_ENCRYPTION_ENABLED', true),
];

Or simply setting the the DB_ENCRYPTION_ENABLED environment variable to true, via the Laravel .env file or hosting environment.

DB_ENCRYPTION_ENABLED=true

Usage

Use the HasEncryptedAttributes trait in any Eloquent model that you wish to apply encryption to and define a protected $encrypted array containing a list of the attributes to encrypt.

For example:

    use AustinHeap\Database\Encryption\Traits\HasEncryptedAttributes;

    class User extends Eloquent {
        use HasEncryptedAttributes;
       
        /**
         * The attributes that should be encrypted on save.
         *
         * @var array
         */
        protected $encrypted = [
            'address_line_1', 'first_name', 'last_name', 'postcode'
        ];
    }

You can combine $casts and $encrypted to store encrypted arrays. An array will first be converted to JSON and then encrypted.

For example:

    use AustinHeap\Database\Encryption\Traits\HasEncryptedAttributes;

    class User extends Eloquent {
        use HasEncryptedAttributes;

        protected $casts     = ['extended_data' => 'array'];
        protected $encrypted = ['extended_data'];
    }

By including the HasEncryptedAttributes trait, the setAttribute() and getAttributeFromArray() methods provided by Eloquent are overridden to include an additional step. This additional step simply checks whether the attribute being accessed via setter/getter is included in the $encrypted array on the model, and then encrypts or decrypts it accordingly.

Keys and IVs

The key and encryption algorithm used is the default Laravel Encrypter service, and configured in your config/app.php:

    'key' => env('APP_KEY', 'SomeRandomString'),
    'cipher' => 'AES-256-CBC',

If you're using AES-256-CBC as the cipher for encrypting data, use the built in command to generate your application key if you haven't already with php artisan key:generate. If you are encrypting longer data, you may want to consider the AES-256-CBC-HMAC-SHA1 cipher.

The IV for encryption is randomly generated and cannot be set.

Unit Tests

This package has aggressive unit tests built with the wonderful orchestral/testbench package which is built on top of PHPUnit. A MySQL server required for execution of unit tests.

There are code coverage reports for laravel-database-encryption available online.

Overrides

The following Laravel 5.5 methods from Eloquent are affected by this trait.

  • constructor() -- calls fill().
  • fill() -- calls setAttribute() which has been extended to encrypt the data.
  • hydrate() -- TBD.
  • create() -- calls constructor() and hence fill().
  • firstOrCreate() -- calls constructor().
  • firstOrNew() -- calls constructor().
  • updateOrCreate() -- calls fill().
  • update() -- calls fill().
  • toArray() -- calls attributesToArray().
  • jsonSerialize() -- calls toArray().
  • toJson() -- calls toArray().
  • attributesToArray() -- calls getArrayableAttributes().
  • getAttribute() -- calls getAttributeValue().
  • getAttributeValue() -- calls getAttributeFromArray().
  • getAttributeFromArray() -- calls getArrayableAttributes().
  • getArrayableAttributes() -- extended to decrypt data.
  • setAttribute() -- extended to encrypt data.
  • getAttributes() -- extended to decrypt data.
  • castAttribute() -- extended to cast encrypted data.
  • isDirty() -- extended to recognize encrypted data.

FAQ

Can I manually encrypt or decrypt arbitrary data?

Yes! You can manually encrypt or decrypt data using the encryptedAttribute() and decryptedAttribute() functions. For example:

    $user = new User();
    $encryptedEmail = $user->encryptedAttribute(Input::get('email'));

Can I search encrypted data?

No! You will not be able to search on attributes which are encrypted by this package because...it is encrypted. Comparing encrypted values would require a fixed IV, which introduces security issues.

If you need to search on data then either:

  • Leave it unencrypted, or
  • Hash the data and search on the hash instead of the encrypted value using a well known hash algorithm such as SHA256.

You could store both a hashed and an encrypted value, using the hashed value for searching and retrieve the encrypted value as needed.

Can I encrypt all my User model data?

No! The same issue with searching also applies to authentication because authentication requires search.

Is this package compatible with elocryptfive out-of-the-box?

No! While it is a (more modern) replacement, it is not compatible directly out of the box. To migrate to this package from elocryptfive, you must:

  1. Decrypt all the data in your database encrypted by elocryptfive.
  2. Remove any calls to elocryptfive from your models/code.
  3. Remove elocryptfive from your composer.json and run composer update.
  4. At this point you should have no encrypted data in your database and all calls/references, but make sure elocryptfive is completely purged.
  5. Follow the installation instructions above.
  6. ???
  7. Profit!

A pull request for automated migrations is more than welcome but is currently out of the scope of this project's goals.

Is this package compatible with insert-random-Eloquent-package-here?

Probably not! It's not feasible to guarantee interoperability between random packages out there, especially packages that also heavily modify Eloquent's default behavior.

Issues and pull requests regarding interoperability will not be accepted.

Implementations

The following decently-trafficed sites use this package in production:

Credits

This is a fork of delatbabel/elocryptfive, which was a fork of dtisgodsson/elocrypt, which was based on earlier work.

Contributing

Pull requests welcome! Please see the contributing guide for more information.

License

The MIT License (MIT). Please see License File for more information.

laravel-database-encryption's People

Contributors

austinheap avatar funkjedi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-database-encryption's Issues

Unchanged attributes are re-encrypted

Hi, not sure if this is a bug or intentional?

When I update a model unchanged attributes are re-encrypted. Could/should there be a comparison with the saved unencrypted value first and only encrypt if they are different?

min required PHP version

Hi There,
This package has min required PHP 7.1.0, Laravel 5.5 itself has min required PHP 7.0.0. Can this package use for 7.0?

Thanks

Laravel 5.7.* compatability

Hey, thanks so much for putting this package together. There is requirement of Laravel 5.5.* with this package.

Do you have any current plans on bumping this? if so any ETA?

If we were to make a PR - do you think it should be a quick win? Or are there likley to be issues?

Many thanks, looking forward to using it - Really nicely put together.

Missed DATABASE_ENCRYPTION_ENABLED in docs

You missed a DB_ENCRYPTION_ENABLED in the docs:

Or simply setting the the DB_ENCRYPTION_ENABLED environment variable to true, via the Laravel .env file or hosting environment.

DATABASE_ENCRYPTION_ENABLED=true

Usage

Encryption broken after Laravel code change

Due to a code change in Laravel code identified in #28, the package no longer works because no encrypted values are stored for the models.

This code change introduced 21 days ago affects all Laravel Versions (5.5, 5.6 and 5.7).

I've set up a gist with a sample use case. I want to save email drivers config so that the users can send emails from different sources. As they contain sensitive information (server address, password, etc.) it is better to store them encrypted.

For the sample use case, include the source code from the gist, call the seeder in the DatabaseSeeder file with $this->call(SendersTableSeeder::class); and then just run php artisan migrate:fresh --seed.

In the database there should be a row in the senders table with the mail_config column set with the encrypted value. Due to the code not working it shows the unencrypted value: {"driver":"log","host":null,"port":null,"username":null,"password":null,"encryption":null,"from":{"address":"admin@localhost","name":"Local Admin"}}

Cant put the encrypted field in the database

When i want to seed the encrypted field in the database it sais:

SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'first_name' at row 1

Where can i set the length of the encrypted string

Is there a way to encrypt old-unencrypted data?

I added this package after i already had data in database, so I am looking to encrypt old data. I was initially thinking of updating updated_at and saving the model and it would encrypt, but it does not cause the encrypted attribute is not considered dirty. Any idea/hint on how i might encode old data?

Type Error: won't decrypt float

i have a column with existing data (a float) in it. i converted the mariadb data type from decimal to varchar. installed laravel-database-encryption, re-saved the data in my app and laravel-database-encryption was able to encrypt it. however, when i went to view the data in my app again, laravel-database-encryption wasn't able to decrypt it. The error can probably speak for itself.

Type error: Return value of App\Models\Entry::decryptedAttribute() must be of the type string or null, float returned

…/vendor/austinheap/laravel-database-encryption/src/Traits/HasEncryptedAttributes.php 173

i understand that the data needs to be stored as some type of text in the database and it is, but i need to be able to encrypt/decrypt any data type. Maybe i'm missing something? FYI, i just reinstalled elocrypt and it handles this same scenario fine.

thanks

Need help with `DB_ENCRYPTION_VERSIONING=false` in .env file

Thank you for a great extension, it's very smooth to integrate!

We have some tables with personal data, which we want to be encrypted. One small consideration was database size and we started configuring header generation, currently configuration looks like this:

# somewhere in .env file
DB_ENCRYPTION_ENABLED=true
DB_ENCRYPTION_PREFIX=:
DB_ENCRYPTION_VERSIONING=false

what produces following results: :versionVERSION-00-01-02typestring[native]... (output from console select command).

And I got stuck with disabling versionVERSION-00-01-02typestring[native] and need help: how to disable it?

Not encrypting files on storing/creating db record

Hey,

The records are not being encrypted when I am creating/storing new info in the database, but on UPDATE action they are being encrypted. Dont know what I am doing wrong here but would help any guidance.

Thanks.

Type error: substr() expects parameter 2 to be integer, boolean given

When using the decryptedAttribute function on an encrypted value, I get the following error:

Symfony\Component\Debug\Exception\FatalThrowableError : Type error: substr() expects parameter 2 to be integer, boolean given

at C:\wamp\www\lifestream\vendor\austinheap\laravel-database-encryption\src\Traits\HasEncryptedAttributes.php: 171

I am encrypting/decrypting data from a migration to ensure that existing data will still work.

My migration looks like this:

class EncryptData extends Migration
{
    public function up()
    {
        $this->encryptModels(SomeModel::all());
    }

    public function down()
    {
        $this->decryptModels(SomeModel::all());
    }

    private function encryptModels($models)
    {
        foreach ($models as $model)
        {
            if (!property_exists($model, 'encrypted'))
                return;
            foreach ($model->encrypted as $key)
            {
                $value = $model->getAttributeRaw($key);
                $value = $model->encryptedAttribute($value);
                $model->setAttributeRaw($key, $value);
                $model->save();
            }
        }
    }

    private function decryptModels($models)
    {
        foreach ($models as $model)
        {
            if (!property_exists($model, 'encrypted'))
                return;
            foreach ($model->encrypted as $key)
            {
                $value = $model->getAttributeRaw($key);
                $value = $model->decryptedAttribute($value);
                $model->setAttributeRaw($key, $value);
                $model->save();
            }
        }
    }
}

The encryption part works fine, but rolling back the migration throws the exception. Also, the encrypted values look like this:

��__LARAVEL-DATABASE-ENCRYPTED-VERSION-00-01-00__��version�VERSION-00-01-00��type�string[native]��eyJpdiI6IjJEYTJuRkdMeTFTQ1pCNXRCanNvUUE9PSIsInZhbHVlIjoiYlo0d2NIOFwvd1BtNER6OUZIOUpIWGc9PSIsIm1hYyI6IjQ5Mzk2OTNlNTAyZGI1NmJkMmUyZjQyNDZlZWYwYTMzYjM3MzRhOTU2NzAzMDc0OGI1Y2Y4ZjczZTk2ZDdhNjQifQ==

Are the �� characters supposed to look like this?

Decryption not working if APP_KEY is changed

Hi. I have encrypted my data with versioning true and now I have changed my APP_KEY and the decryption is not working. If I change a value then only that is shown in the result set after data retrieval.

Add support for Laravel 5.7

Currently this package cannot be installed with Laravel 5.7 due to the restriction:

"require": {
    "laravel/framework": "5.5.*|5.6.*",
}

Please add support for Laravel 5.7

Migrating Installs

I'm running this package on a site and it's working great 👍

I've provisioned a new server and want to migrate my site — if the Laravel APP_KEY is the same on both systems, should the data remain readable?

showing encrypted value

hi its showing encrypted value needs to show decrypted right

��__LARAVEL-DATABASE-ENCRYPTED-VERSION-00-01-00__��version�VERSION-00-01-00��type�string[native]��ey

Trait 'App\HasEncryptedAttributes' not found

So, I am trying to upgrade my laravel 5.1 install with Elocrypt towards laravel 5.5. Currently I am trying this package to see if it can encrypt and decrypt my old database.

In order to do so, I followed the installation instructions in the readme and made the following changes to the config.

'enabled'            => env('DB_ENCRYPTION_ENABLED', true),
'prefix'             => env('DB_ENCRYPTION_PREFIX', '__ELOCRYPT__'),
'versioning'         => env('DB_ENCRYPTION_VERSIONING', false),

I modified my user.php model:

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use AustinHeap\Database\Encryption;

class User extends Authenticatable
{
    use Notifiable;
    use HasEncryptedAttributes;

    protected $encrypted = [
        'name'
    ];
}

However, running this code gives me the Trait 'App\HasEncryptedAttributes' not found. I am sure I am missing something here, but what?

Standalone version

Hi,

I'm using Eloquent as standalone for my project.
Would it be possible to use this package too to support the standalone Eloquent?

Cannot decrypt model attribute with no package header! Error

I'm able to encrypt the data, an encryption header is written, but it's not detected by the plugin.
If i use the normal getter i.e. $user->name or $user->getAttribute('name'), I get the encrypted string in return.
\u0001\u0002__LARAVEL-DATABASE-ENCRYPTED-VERSION-00-01-02__\u0003\u001eversion\u0019VERSION-00-01-02\u0017\u001etype\u0019string[native]\u0017\u0004eyJpdiI6IlJndER1VWQ4ek1PVGhSRk5MRjNwWGc9PSIsInZhbHVlIjoiMXR1

if I use $user->decryptedAttribute('name'), I get the above message.
I can see that the system is looking for the wrong start and end for the header:

array:2 [▼ "start" => array:3 [▼ "int" => 1 "string" => "\x01" "default" => true ] "stop" => array:3 [▼ "int" => 4 "string" => "\x04" "default" => true ] ]

but overriding this values with \u0001 and \u001e didn't make a difference

My db config is standard:
'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'strict' => false, ],

No Encryption then Create new Model instance

Hi,

then I create a new Model, for example a new User, and save it to the Database, the attributes are not encrypted. Then I overwrite some attributes from this Modal and save the updated Model in the database, the updated attributes are encrypted.

How I can fix this?

Thank you

Not every record is encrypted

I have a very robust application that encrypts several fields in a particular table in my database. Initially, everything was working great. I just now discovered that not every newly-created record is getting encrypted. Even records created by the same user is "hit-or-miss". Some records are encrypted by that user, and some aren't. I can't seem to figure out why suddenly things aren't reliably being encrypted. I can't seem to figure out what is going on. Any ideas as to what may have happened? How can I troubleshoot something that "sometimes works"?

Doesn't work with Laravel 5.7

Hello,

i have a problem. I installed the plugin with Laravel 5.7. I have inserted

use AustinHeap\Database\Encryption\Traits\HasEncryptedAttributes;

on top of my Model and defined

 use HasEncryptedAttributes;

 protected $encrypted = [
        'name',
 ];

in it. But after saving the Model in the Database, the Attribute name doesn't encrypted.
Are there any ideas to fix it?

Thank you for your help

Laravel 5.8 support

Thanks for package and good work.

We need to update the package to support Laravel 5.8. Probably there might be some not-compabilities.

Showing encrypted data

After making some migrations, adding some new fields, and making nullable others, the package began to return encrypted values for 'some' of the fields.
For example, I have the password of the db working correctly (it is encrypted and returns the correct value) but I have the name of the encrypted S3 bucket, and it returns the string as it is in the db "__LARAVEL-DATABASE-ENCRYPTED-VERSIO ... "
I can't make it work again ... any idea?

Laravel 5.6 support

Could you update the composer file to allow for Laravel 5.6 and tag a new release?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.