delatbabel/elocryptfive

轻松自动加密和解密Eloquent属性。

v1.5.6 2016-09-22 11:10 UTC

This package is not auto-updated.

Last update: 2024-09-14 17:53:39 UTC


README

Build Status StyleCI Latest Stable Version Total Downloads

自动加密和解密Laravel 5 Eloquent值。

请先阅读

加密值通常比明文值长。有时会很长。你可能需要扩展数据库表中列的宽度以存储加密值。

如果你正在加密长字符串,如JSON数据块,则加密值可能超过VARCHAR字段支持的长度,你可能需要将列类型扩展到TEXT或LONGTEXT。

这能做什么?

这通过在Laravel应用程序中透明地加密数据库表中存储的列,并在将数据存储在模型属性时加密数据,在从模型属性检索数据时解密数据来实现。

所有加密的数据都会以一个标签(默认为__ELOCRYPT__:)为前缀,以便轻松识别加密数据。

这支持存储加密或非加密数据的列,以便简化迁移。无论数据是否加密,都可以正确地从列中读取数据,但在将其保存回这些列时将自动加密。

需求和推荐

  • Laravel 5.1 LTS(未在5.2及以后版本上测试)
  • PHP > 5.6.0(需要PHP 5.6中添加的hash_equals()函数)
  • PHP openssl扩展
  • 在您的操作系统上有一个工作的OpenSSL实现。OpenSSL通常预构建在大多数Linux发行版和其他Unix形式(如*BSD)中。Windows系统上可能没有可工作的OpenSSL实现,这取决于您的LA?P堆栈如何构建。我不能为没有OpenSSL库的系统提供安装或使用ElocryptFive的支持。

贡献者

这是Darren Taylor的Laravel 4 "elocrypt"包,已移植到Laravel 5。我做了以下添加/更改

  • 在单独的函数中进行加密(encryptedAttribute和decryptedAttribute而不是在__set和__get中,并从setAttribute和getAttribute调用这些函数,因为这对于具有新casts功能的Laravel 5更合适。例如,您可以将字段添加到$casts$encrypts中,以便数组可以首先转换为JSON字符串,然后加密。它也应该适用于Lumen。

  • 将所有加密值前缀为标签字符串(默认为__ELOCRYPT__:),以便检测和处理纯文本数据。将现有数据库中的所有纯文本数据更新为加密数据的脚本编写任务留给了读者。

原始Laravel 4包在这里:https://github.com/dtisgodsson/elocrypt

感谢Brandon Surowiec对内部方法的大量重构。

安装

可以通过将以下内容添加到您的composer.json文件中来安装此包

    "require": {
        "delatbabel/elocryptfive": "~1.0"
    }

然后运行以下命令

    composer update

一旦composer update完成,请将服务提供者添加到应用程序的config/app.php文件中的providers数组中

    'providers' => [
        ...
        Delatbabel\Elocrypt\ElocryptServiceProvider::class,
    ],

配置

使用以下命令发布配置文件

    php artisan vendor:publish --provider='Delatbabel\Elocrypt\ElocryptServiceProvider'

然后您可以在.env配置文件中更改默认的前缀标签字符串

    ELOCRYPT_PREFIX=__This_is_encrypted_data__

或者您可以直接在config/elocrypt.php文件中更改默认设置

    return [
        'prefix' => env('ELOCRYPT_PREFIX', '__This_is_encrypted_data__')
    ]

用法

只需在您希望应用加密的任何 Eloquent 模型中引用 Elocrypt 特性,并定义一个包含要加密的属性列表的 $encrypts 数组。

例如:

    use Delatbabel\Elocrypt\Elocrypt;

    class User extends Eloquent {

        use Elocrypt;
       
        /**
         * The attributes that should be encrypted on save.
         *
         * @var array
         */
        protected $encrypts = [
            'address_line_1', 'first_name', 'last_name', 'postcode'
        ];
    }

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

例如:

    use Delatbabel\Elocrypt\Elocrypt;

    class User extends Eloquent {

        use Elocrypt;

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

        protected $encrypts = ['extended_data'];
    }

它是如何工作的?

通过包含 Elocrypt 特性,Eloquent 提供的 setAttribute() 和 getAttributeFromArray() 方法被重写,包括一个额外的步骤。这个额外的步骤简单地检查要设置或获取的属性是否包含在模型上的 $encrypts 数组中,并根据需要进行加密/解密。

Illuminate\Database\Eloquent\Model 中的方法总结

本节概述了 Laravel v 5.1.12 中 Laravel 模型类的主要方法,并检查这些模型如何设置属性以及它们如何受此特性影响。

  • 构造函数 -- 调用 fill()
  • fill() -- 调用已经扩展以加密数据的 setAttribute()
  • hydrate() -- 待定
  • create() -- 调用构造函数,因此 fill()
  • firstOrCreate -- 调用构造函数
  • firstOrNew -- 调用构造函数
  • updateOrCreate -- 调用 fill()
  • update() -- 调用 fill()
  • toArray() -- 调用 attributesToArray()
  • jsonSerialize() -- 调用 toArray()
  • toJson() -- 调用 toArray()
  • attributesToArray() -- 调用 getArrayableAttributes().
  • getAttribute -- 调用 getAttributeValue()
  • getAttributeValue -- 调用 getAttributeFromArray()
  • getAttributeFromArray -- 调用 getArrayableAttributes()
  • getArrayableAttributes -- 已在此处扩展以解密数据。
  • setAttribute -- 已在此处扩展以加密数据。
  • getAttributes -- 已在此处扩展以解密数据。

密钥和 IV

使用的密钥和加密算法遵循 Laravel Encrypter 服务,并在 config/app.php 中定义如下:

    'key' => env('APP_KEY', 'SomeRandomString'),

    'cipher' => 'AES-256-CBC',

我建议生成一个随机的 32 个字符的字符串作为加密密钥,并使用 AES-256-CBC 作为加密数据的密文。如果您正在加密长的数据字符串,那么 AES-256-CBC-HMAC-SHA1 会更好。

加密的 IV 是随机生成的。

常见问题解答

手动加密数据

您可以使用 encryptedAttribute()decryptedAttribute() 函数手动加密或解密数据。以下是一个示例:

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

加密和搜索

由于加密,您将无法在加密数据上搜索,因为它是加密的。比较加密值需要固定的 IV,这会引入安全问题。

如果您需要搜索数据,那么您可以选择以下操作:

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

您可以在哈希值和加密值之间进行存储,使用哈希值进行搜索,并检索加密值用于其他用途。

加密和身份验证

由于搜索的问题,身份验证也适用,因为身份验证需要用户搜索。

如果您有一个包含加密用户数据(例如登录数据,例如电子邮件)的身份验证表,这将阻止 Auth::attempt 的工作。例如,以下代码将不起作用:

    $auth = Auth::attempt(array(
                "email"     =>  Input::get("email"),
                "password"  =>  Input::get("password"),
    ), $remember);

对于搜索,比较加密的电子邮件将不起作用,因为它需要固定的 IV,这会引入安全问题。

您需要做的替代方案是使用知名的哈希函数(例如 SHA256 或 RIPE-MD160)对电子邮件地址进行哈希处理,而不是加密它,然后在 Auth::attempt 函数中比较哈希值。

如果您需要访问电子邮件地址,则可以在哈希值和加密值之间进行存储,使用哈希值进行身份验证,并检索加密值用于其他用途(例如发送电子邮件)。