involix / elocryptseven
Requires
- php: >=7.0.0
- illuminate/config: ^5.0|^6.0|^7.0|^8.0
- illuminate/console: ^5.0|^6.0|^7.0|^8.0
- illuminate/container: ^5.0|^6.0|^7.0|^8.0
- illuminate/contracts: ^5.0|^6.0|^7.0|^8.0
- illuminate/encryption: ^5.0|^6.0|^7.0|^8.0
- illuminate/support: ^5.0|^6.0|^7.0|^8.0
- paragonie/random_compat: ^9.99.99
Requires (Dev)
- phpunit/phpunit: ^5.0|^6.0|^7.0|^8.0|^9.0
README
自动加密和解密 Laravel Eloquent 值。
首先阅读
加密值通常比明文值长。有时会很长。您可能会发现数据库表中的列宽度需要扩展以存储加密值。
如果您正在加密像 JSON 块这样的长字符串,则加密值可能会超过 VARCHAR 字段的支持范围,您可能需要将列类型扩展到 TEXT 或 LONGTEXT。
此工具的功能是什么?
此工具通过在存储在模型属性中的数据上加密并在从模型属性检索数据时解密,透明地对 Laravel 应用程序中数据库表存储的列进行加密和解密。
所有加密的数据都带有标签(默认 __ELOCRYPT__:
),以便可以轻松识别加密数据。
此工具支持存储加密或非加密数据的列,以便于迁移。可以正确地从列中读取数据,无论是否加密,但将其保存回这些列时会自动加密。
要求和推荐
- Laravel 5+
- PHP > 7
- PHP openssl 扩展。
- 操作系统上的 OpenSSL 实现有效。大多数 Linux 发行版和其他形式的 Unix(如 *BSD)都预装了 OpenSSL。在 Windows 系统上是否有一个有效的 OpenSSL 实现取决于您的 LA?P 堆栈是如何构建的。对于没有 OpenSSL 库的系统,我无法提供安装或使用 ElocryptFive 的支持。
贡献者
这是 Darren Taylor 的 Laravel 4 "elocrypt" 包,由 Eugene Cooper 转移到 Laravel 6/7/8。
感谢 Brandon Surowiec 对内部方法的广泛重构。
安装
此包可以通过添加以下内容到您的 composer.json
文件来通过 Composer 安装
"require": {
"involix/elocrypt": "^1.8"
}
然后运行以下命令
composer update
一旦 composer update
完成,然后在应用程序的 config/app.php
文件中的 providers
数组中添加服务提供者
'providers' => [ ... Involix\Elocrypt\ElocryptServiceProvider::class, ],
配置
通过以下命令发布配置文件
php artisan vendor:publish --provider='Involix\Elocrypt\ElocryptServiceProvider'
然后您可以在 .env
配置文件中更改默认的前缀标签字符串
ELOCRYPT_PREFIX=__encrypted__
或者您也可以直接在 config/elocrypt.php
文件中更改默认设置
return [ 'prefix' => env('ELOCRYPT_PREFIX', '__encrypted__') ]
用法
只需在任何需要应用加密的Eloquent模型中引用Elocrypt特性,并定义一个包含要加密的属性列表的$encrypts
数组。
例如
use Involix\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 Involix\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 Model类中的主要方法,并检查了这些模型如何设置属性以及它们如何受此特性影响。
- 构造函数 -- 调用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函数中比较哈希值。
如果你需要访问电子邮件地址,可以存储哈希和加密的电子邮件地址,使用哈希值进行身份验证,并检索加密值用于其他用途(例如发送电子邮件)。