spatie / laravel-ciphersweet
在您的Laravel项目中使用ciphersweet
Requires
- php: ^8.1
- illuminate/contracts: ^9.19|^10.0|^11.0
- paragonie/ciphersweet: ^4.0.1
- spatie/laravel-package-tools: ^1.12.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.8
- nunomaduro/collision: ^6.0|^8.0
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^7.0|^8.0|^9.0
- pestphp/pest: ^1.21|^2.34
- pestphp/pest-plugin-laravel: ^1.1|^2.3
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.5|^10.5
- spatie/laravel-ray: ^1.26
README
在您的项目中,您可能会在数据库中存储敏感的个人数据。如果未经授权的人访问了您的数据库,所有敏感数据都可以被读取,这显然是不好的。
为了解决这个问题,您可以加密个人数据。这样,未经授权的人无法读取它,但您的应用程序仍然可以在需要显示或处理数据时解密它。
CipherSweet 是由 Paragon Initiative Enterprises 开发的后端库,用于实现 可搜索的字段级加密。它可以以非常安全的方式加密和解密值。它还能够创建盲索引。这些索引可以用于在加密数据上执行搜索。这些索引本身对人类是不可读的。
我们的包是CipherSweet的包装器,允许您轻松地与Laravel的Eloquent模型一起使用。
支持我们
我们投入了大量资源来创建 最佳开源包。您可以通过 购买我们的付费产品之一 来支持我们。
我们非常感谢您从您的家乡寄来明信片,并说明您正在使用我们的哪个包。您可以在 我们的联系页面 上找到我们的地址。我们将在 我们的虚拟明信片墙上 发布所有收到的明信片。
安装
您可以通过composer安装此包
composer require spatie/laravel-ciphersweet
您必须使用以下命令发布并运行迁移
php artisan vendor:publish --tag="ciphersweet-migrations"
php artisan migrate
可选地,您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="ciphersweet-config"
这是配置文件的内容
return [ /* * This controls which cryptographic backend will be used by CipherSweet. * Unless you have specific compliance requirements, you should choose * "nacl". * * Supported: "boring", "fips", "nacl" */ 'backend' => env('CIPHERSWEET_BACKEND', 'nacl'), /* * Select which key provider your application will use. The default option * is to read a string literal out of .env, but it's also possible to * provide the key in a file or use random keys for testing. * * Supported: "file", "random", "string" */ 'provider' => env('CIPHERSWEET_PROVIDER', 'string'), /* * Set provider-specific options here. "string" will read the key directly * from your .env file. "file" will read the contents of the specified file * to use as your key. "custom" points to a factory class that returns a * provider from its `__invoke` method. Please see the docs for more details. */ 'providers' => [ 'file' => [ 'path' => env('CIPHERSWEET_FILE_PATH'), ], 'string' => [ 'key' => env('CIPHERSWEET_KEY'), ], ], /* * The provided code snippet checks whether the $permitEmpty property is set to false * for a given field. If it is not set to false, it throws an EmptyFieldException indicating * that the field is not defined in the row. This ensures that the code enforces the requirement for * the field to have a value and alerts the user if it is empty or undefined. * Supported: "true", "false" */ 'permit_empty' => env('CIPHERSWEET_PERMIT_EMPTY', FALSE) ];
用法
存储加密值需要几个步骤。让我们看看它们。
1. 准备您的模型并选择要加密的属性
将CipherSweetEncrypted
接口和UsesCipherSweet
特征添加到您想要添加加密字段到模型中。
您需要实现configureCipherSweet
方法来配置CipherSweet。
use Spatie\LaravelCipherSweet\Contracts\CipherSweetEncrypted; use Spatie\LaravelCipherSweet\Concerns\UsesCipherSweet; use ParagonIE\CipherSweet\EncryptedRow; use ParagonIE\CipherSweet\BlindIndex; use Illuminate\Database\Eloquent\Model; class User extends Model implements CipherSweetEncrypted { use UsesCipherSweet; /** * Encrypted Fields * * Each column that should be encrypted should be added below. Each column * in the migration should be a `text` type to store the encrypted value. * * ``` * ->addField('column_name') * ->addBooleanField('column_name') * ->addIntegerField('column_name') * ->addTextField('column_name') * ``` * * Optional Fields * * These do not encrypt when NULL is provided as a value. * Instead, they become an unencrypted NULL. * * ``` * ->addOptionalTextField('column_name') * ->addOptionalBooleanField('column_name') * ->addOptionalFloatField('column_name') * ->addOptionalIntegerField('column_name') * ``` * * A JSON array can be encrypted as long as the key structure is defined in * a field map. See the docs for details on defining field maps. * * ``` * ->addJsonField('column_name', $fieldMap) * ``` * * Each field that should be searchable using an exact match needs to be * added as a blind index. Partial search is not supported. See the docs * for details on bit sizes and how to use compound indexes. * * ``` * ->addBlindIndex('column_name', new BlindIndex('column_name_index')) * ``` * * @see https://github.com/spatie/laravel-ciphersweet * @see https://ciphersweet.paragonie.com/ * @see https://ciphersweet.paragonie.com/php/blind-index-planning * @see https://github.com/paragonie/ciphersweet/blob/master/src/EncryptedRow.php * * @param EncryptedRow $encryptedRow * * @return void */ public static function configureCipherSweet(EncryptedRow $encryptedRow): void { $encryptedRow ->addField('email') ->addBlindIndex('email', new BlindIndex('email_index')); } }
上面的示例将在User
模型上加密email
字段。它还在blind_indexes
表中添加了一个盲索引,允许您对其搜索。
有关更多信息,请参阅 CipherSweet PHP 文档。
2. 生成加密密钥
加密密钥用于加密您的值。您可以使用以下命令生成新的CipherSweet加密密钥
php artisan ciphersweet:generate-key
3. 更新您的.env文件
生成密钥后,您应将生成的CipherSweet密钥添加到您的.env文件中。
CIPHERSWEET_KEY=<YOUR-KEY>
密钥将用于您的应用程序管理加密值。
4. 加密模型属性
有了这些,您可以通过运行以下命令来加密所有值
php artisan ciphersweet:encrypt <your-model-class> <generated-key>
该命令将更新模型的所有加密字段和盲索引。
如果您有很多行,此过程可能需要很长时间。该命令可重启:可以重新运行,无需重新加密已旋转的密钥。
在盲索引上进行搜索
即使值已加密,您仍可以使用盲索引进行搜索。在您运行加密模型值的命令时,将构建盲索引。
此包提供了 whereBlind
和 orWhereBlind
范围,用于在盲索引上进行搜索。
第一个参数是列,第二个是调用 ->addBlindIndex
时设置的索引名称,第三个是原始值,包将自动应用任何转换并将值哈希以在盲索引上进行搜索。
$user = User::whereBlind('email', 'email_index', 'rias@spatie.be');
密钥旋转
如果您怀疑有人获得了您的加密密钥,您可以重新加密值。只需生成另一个加密密钥,然后再次运行 php artisan ciphersweet:encrypt
命令。
php artisan ciphersweet:encrypt "App\User" <your-new-key>
这将更新模型的所有加密字段和盲索引。完成后,您可以更新环境或配置文件以使用新密钥。
实现自定义后端
您可以通过将 ciphersweet.backend
配置值设置为 custom
来实现自定义后端。
然后必须将 ciphersweet.backend.custom
配置值设置为可调用的工厂类,该类返回 ParagonIE\CipherSweet\Contract\BackendInterface
的实现。
class CustomBackendFactory { public function __invoke() { return new CustomBackend(); } } class CustomBackend implements BackendInterface { public function encrypt(string $plaintext, SymmetricKey $key, string $aad = ''): string { // Your logic here. } public function decrypt(string $ciphertext, SymmetricKey $key, string $aad = ''): string { // Your logic here. } public function blindIndexFast(string $plaintext, SymmetricKey $key, ?int $bitLength = null): string { // Your logic here. } public function blindIndexSlow(string $plaintext, SymmetricKey $key, ?int $bitLength = null, array $config = []): string { // Your logic here. } public function getIndexTypeColumn(string $tableName, string $fieldName, string $indexName): string { // Your logic here. } public function deriveKeyFromPassword(string $password, string $salt): SymmetricKey { // Your logic here.return new SymmetricKey('123'); } public function doStreamDecrypt($inputFP, $outputFP, SymmetricKey $key, int $chunkSize = 8192, ?AAD $aad = null): bool { // Your logic here. } public function doStreamEncrypt($inputFP, $outputFP, SymmetricKey $key, int $chunkSize = 8192, string $salt = Constants::DUMMY_SALT, ?AAD $aad = null): bool { // Your logic here. } public function getFileEncryptionSaltOffset(): int { // Your logic here. } public function getPrefix(): string { // Your logic here. } }
实现自定义密钥提供程序
您可以通过将 ciphersweet.provider
配置值设置为 custom
来实现自定义密钥提供程序。
然后必须将 ciphersweet.providers.custom
配置值设置为可调用的工厂类,该类返回 ParagonIE\CipherSweet\Contract\KeyProviderInterface
的实现。
class CustomKeyProviderFactory { public function __invoke() { return new CustomKeyProvider(); } } class CustomKeyProvider implements KeyProviderInterface { public function getSymmetricKey(): SymmetricKey { return new SymmetricKey(''); // Your logic here. } }
测试
composer test
更改日志
有关最近更改的更多信息,请参阅更改日志。
贡献
有关详细信息,请参阅贡献指南。
安全漏洞
请审查我们的安全策略以了解如何报告安全漏洞。
鸣谢
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。