ricardosierra/laravel-database-encryption

一个用于自动加密和解密Laravel 5.5+中的Eloquent属性(基于配置设置)的包。


README

laravel-database-encryption banner from the documentation

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

一个用于自动加密和解密Laravel 5.5+中的Eloquent属性(基于配置设置)的包。

本项目旨在创建一个易于安装、配置后即可自动加密和解密数据库中存储的Eloquent模型属性的包。因此,它具有一定的意见性,但为了配置而构建。

启用后,它会自动开始加密存储在模型属性中的数据,并在从模型属性中检索数据时进行解密。

所有加密的数据都带有头信息,以便轻松识别加密数据、轮换加密密钥以及(可选)对加密数据格式的版本进行控制。

这支持存储加密或非加密数据的列,以便于迁移。无论数据是否加密,都可以正确地从列中读取数据,但将其保存回这些列时将自动加密。即使数据库中存储的底层值被此包加密,标准的Laravel Eloquent功能(如属性类型转换)仍将继续正常工作。

有关laravel-database-encryption的文档可在网上找到,其源文件位于docs/目录中。从HasEncryptedAttributes特性的文档开始阅读最为合理。

目录

要求

  • Laravel:5.5、5.6或5.7
  • PHP:7.1、7.2或7.3
  • PHP OpenSSL扩展

状态

架构

加密值通常比明文值长,有时长得多。您可能会发现数据库表中的列宽度需要更改,以存储此包生成的加密值。

如果您正在加密长字符串,如JSON blob,则加密值可能比VARCHAR字段支持的长度要长,您需要将列类型更改为TEXTLONGTEXT

常见问题解答中包含有关从elocryptfive迁移的迁移说明。

安装

第1步:Composer

通过Composer命令行

$ composer require austinheap/laravel-database-encryption

或将包添加到您的composer.json

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

第2步:启用包(可选)

本包实现了Laravel自动发现功能。安装后,包提供者和外观会自动添加。

如果您想显式声明提供者和/或别名,请先在config/app.php文件中添加服务提供者

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

然后,将别名添加到您的config/app.php文件中

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

第3步:配置包

发布包配置文件

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

现在,您可以通过编辑config/database-encryption.php文件来启用Eloquent模型的自动加密和解密

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

或者简单地将环境变量DB_ENCRYPTION_ENABLED设置为true,通过Laravel的.env文件或托管环境实现

DB_ENCRYPTION_ENABLED=true

用法

在您想要应用加密的任何Eloquent模型中,使用HasEncryptedAttributes特性,并定义一个包含要加密的属性列表的protected $encrypted数组。

例如

    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'
        ];
    }

您可以将$casts$encrypted结合起来存储加密数组。数组首先会被转换为JSON,然后进行加密。

例如

    use AustinHeap\Database\Encryption\Traits\HasEncryptedAttributes;

    class User extends Eloquent {
        use HasEncryptedAttributes;

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

通过包含HasEncryptedAttributes特性,Eloquent提供的setAttribute()getAttributeFromArray()方法被重写,包括一个额外的步骤。这个额外的步骤只是简单地检查通过setter/getter访问的属性是否包含在模型上的$encrypted数组中,然后根据需要对其进行加密或解密。

密钥和IV

使用的密钥和加密算法是默认的Laravel Encrypter服务,并在您的config/app.php中进行配置

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

如果您使用AES-256-CBC作为加密数据的加密方式,如果您尚未生成应用密钥,请使用内置命令php artisan key:generate生成。如果您正在加密较长的数据,您可能想要考虑使用AES-256-CBC-HMAC-SHA1加密方式。

加密的IV是随机生成的,无法设置。

单元测试

此包使用orchestral/testbench包(基于PHPUnit构建)构建了激进的单元测试。单元测试的执行需要一个MySQL服务器。

在线有laravel-database-encryption的代码覆盖率报告

覆盖

以下Laravel 5.5的Eloquent方法受到此特性的影响。

  • constructor() -- 调用fill()
  • fill() -- 调用setAttribute(),它已扩展以加密数据。
  • hydrate() -- 待定。
  • create() -- 调用constructor(),从而调用fill()
  • firstOrCreate() -- 调用constructor()
  • firstOrNew() -- 调用constructor()
  • updateOrCreate() -- 调用fill()
  • update() -- 调用fill()
  • toArray() -- 调用attributesToArray()
  • jsonSerialize() -- 调用toArray()
  • toJson() -- 调用toArray()
  • attributesToArray() -- 调用getArrayableAttributes()
  • getAttribute() -- 调用getAttributeValue()
  • getAttributeValue() -- 调用getAttributeFromArray()
  • getAttributeFromArray() -- 调用getArrayableAttributes()
  • getArrayableAttributes() -- 扩展以解密数据。
  • setAttribute() -- 扩展以加密数据。
  • getAttributes() -- 扩展以解密数据。
  • castAttribute() -- 扩展以转换加密数据。
  • isDirty() -- 扩展以识别加密数据。

常见问题解答

我能否手动加密或解密任意数据?

是的!您可以使用encryptedAttribute()decryptedAttribute()函数手动加密或解密数据。例如

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

我能否搜索加密数据?

不!您将无法搜索此包加密的属性,因为……它是加密的。比较加密值需要固定的IV,这会引入安全问题。

如果您需要在数据上搜索,则可以选择以下操作:

  • 保持数据未加密,或者
  • 使用如SHA256之类的知名哈希算法对数据进行哈希处理,并在哈希值上搜索,而不是在加密值上搜索。

您可以将哈希值和加密值都存储起来,使用哈希值进行搜索,并在需要时检索加密值。

我能否加密所有User模型数据?

不行!与搜索相同的问题也适用于身份验证,因为身份验证需要搜索。

这个包是否与elocryptfive直接兼容?

不兼容!虽然它是一个(更现代的)替代品,但直接使用时不兼容。要从elocryptfive迁移到这个包,您必须

  1. 解密数据库中所有由elocryptfive加密的数据。
  2. 从您的模型/代码中移除对elocryptfive的所有调用。
  3. 从您的composer.json中移除elocryptfive并运行composer update
  4. 此时,您的数据库中应该没有加密数据,也没有任何调用/引用,但请确保已完全清除elocryptfive。
  5. 按照上面的安装说明进行操作。
  6. ???
  7. 盈利!

欢迎提交用于自动化迁移的拉取请求,但当前这超出了本项目目标范围。

此包与insert-random-Eloquent-package-here是否兼容?

可能不行!保证随机包之间的互操作性是不可行的,特别是那些也严重修改Eloquent默认行为的包。

关于互操作性的问题和拉取请求将不予接受。

实现

以下流量较好的网站在生产中使用此包:

致谢

这是delatbabel/elocryptfive的分支,后者是dtisgodsson/elocrypt的分支,而dtisgodsson/elocrypt是基于早期工作的。

贡献

欢迎提交拉取请求!请参阅贡献指南了解更多信息。

许可证

MIT 许可证(MIT)。请参阅许可证文件了解更多信息。