enflow/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, 5.8, 或 6.x
  • 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() 方法被覆盖,以包含一个额外的步骤。这个额外的步骤只是检查通过设置器/获取器访问的属性是否包含在模型上的 $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. 盈利!

欢迎提交自动迁移的 pull request,但目前这超出了本项目目标范围。

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

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

不会接受有关互操作性的问题和 pull request。

实现

以下流量不错的网站在生产中使用此包

致谢

这是 delatbabel/elocryptfive 的分支,它是一个 dtisgodsson/elocrypt 的分支,而 dtisgodsson/elocrypt 是基于早期工作的。

贡献

欢迎提交 pull request!请参阅贡献指南以获取更多信息。

许可

MIT 许可证 (MIT)。请参阅 许可文件 以获取更多信息。