spatie/laravel-ciphersweet

在您的Laravel项目中使用ciphersweet

1.6.2 2024-07-18 13:03 UTC

This package is auto-updated.

Last update: 2024-09-22 05:55:14 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

在您的项目中,您可能会在数据库中存储敏感的个人数据。如果未经授权的人访问了您的数据库,所有敏感数据都可以被读取,这显然是不好的。

为了解决这个问题,您可以加密个人数据。这样,未经授权的人无法读取它,但您的应用程序仍然可以在需要显示或处理数据时解密它。

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>

该命令将更新模型的所有加密字段和盲索引。

如果您有很多行,此过程可能需要很长时间。该命令可重启:可以重新运行,无需重新加密已旋转的密钥。

在盲索引上进行搜索

即使值已加密,您仍可以使用盲索引进行搜索。在您运行加密模型值的命令时,将构建盲索引。

此包提供了 whereBlindorWhereBlind 范围,用于在盲索引上进行搜索。

第一个参数是列,第二个是调用 ->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)。有关更多信息,请参阅许可证文件