fileinvite-org/laravel-database-encryption

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


README

此包是基于Laravel 5.5+ 数据库加密包的分支和重新包装版本。这是为了支持Laravel 6.x框架,并作为FileInvite内部包使用。

Laravel 数据库加密包

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, 5.8 或 6.x
  • PHP: 7.1, 7.2, 或 7.3
  • PHP OpenSSL 扩展

模式

加密值通常比纯文本值长,有时长得多。您可能需要调整数据库表中列的宽度,以存储此包生成的加密值。

如果您正在加密长字符串,例如JSON数据块,那么加密后的值可能会超过VARCHAR字段的支持长度,您需要将列类型更改为TEXTLONGTEXT

FAQ中包含如果您从elocryptfive迁移时所需的迁移说明。

安装

步骤 1:Composer

通过Composer命令行

$ composer require fileinvite-org/laravel-database-encryption

或将其添加到您的composer.json

{
    "require": {
        "fileinvite-org/laravel-database-encryption": "dev-master"
    }
}

步骤 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),
];

或简单地通过Laravel的.env文件或托管环境设置DB_ENCRYPTION_ENABLED环境变量为true。

DB_ENCRYPTION_ENABLED=true

用法

使用HasEncryptedAttributes特质在您希望应用加密的任何Eloquent模型中,并定义一个包含要加密的属性列表的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

使用的密钥和加密算法是默认的LaravelEncrypter服务,并在您的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的分支,后者基于早期的工作。

贡献

欢迎提交拉取请求!有关更多信息,请参阅贡献指南

许可

MIT许可(MIT)。有关更多信息,请参阅许可文件