{"id":19324851,"url":"https://github.com/spatie/laravel-ciphersweet","last_synced_at":"2026-02-09T17:01:16.628Z","repository":{"id":41190518,"uuid":"508226844","full_name":"spatie/laravel-ciphersweet","owner":"spatie","description":"Use Ciphersweet in your Laravel project","archived":false,"fork":false,"pushed_at":"2026-01-31T09:49:12.000Z","size":141,"stargazers_count":411,"open_issues_count":1,"forks_count":38,"subscribers_count":8,"default_branch":"main","last_synced_at":"2026-01-31T22:27:44.536Z","etag":null,"topics":["laravel","php","privacy","security"],"latest_commit_sha":null,"homepage":"https://spatie.be/open-source","language":"PHP","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spatie.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-06-28T09:01:25.000Z","updated_at":"2026-01-31T09:49:09.000Z","dependencies_parsed_at":"2023-11-07T09:30:43.437Z","dependency_job_id":"44844537-1a9e-4635-ab52-0b73c404963c","html_url":"https://github.com/spatie/laravel-ciphersweet","commit_stats":{"total_commits":97,"total_committers":17,"mean_commits":5.705882352941177,"dds":0.5463917525773196,"last_synced_commit":"edeb667d4d55f7add9ee58e99a580219035bf1ee"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":"spatie/package-skeleton-laravel","purl":"pkg:github/spatie/laravel-ciphersweet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Flaravel-ciphersweet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Flaravel-ciphersweet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Flaravel-ciphersweet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Flaravel-ciphersweet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spatie","download_url":"https://codeload.github.com/spatie/laravel-ciphersweet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Flaravel-ciphersweet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29273138,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-09T13:47:44.167Z","status":"ssl_error","status_checked_at":"2026-02-09T13:47:43.721Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["laravel","php","privacy","security"],"created_at":"2024-11-10T02:07:08.534Z","updated_at":"2026-02-09T17:01:16.622Z","avatar_url":"https://github.com/spatie.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Use CipherSweet in your Laravel project\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/laravel-ciphersweet.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-ciphersweet)\n[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/spatie/laravel-ciphersweet/run-tests.yml?branch=main\u0026label=tests)](https://github.com/spatie/laravel-ciphersweet/actions?query=workflow%3Arun-tests+branch%3Amain)\n[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/spatie/laravel-ciphersweet/php-cs-fixer.yml?branch=main\u0026label=code%20style)](https://github.com/spatie/laravel-ciphersweet/actions?query=workflow%3A\"Check+%26+fix+styling\"+branch%3Amain)\n[![Total Downloads](https://img.shields.io/packagist/dt/spatie/laravel-ciphersweet.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-ciphersweet)\n\nIn your project, you might store sensitive personal data in your database. Should an unauthorised person get access to your DB, all sensitive can be read which is obviously not good.\n\nTo solve this problem, you can encrypt the personal data. This way, unauthorized persons cannot read it, but your application can still decrypt it when you need to display or work with the data.\n\n[CipherSweet](https://ciphersweet.paragonie.com/) is a backend library developed by [Paragon Initiative Enterprises](https://paragonie.com/) for implementing [searchable field-level encryption](https://paragonie.com/blog/2017/05/building-searchable-encrypted-databases-with-php-and-sql). It can encrypt and decrypt values in a very secure way. It is also able to create blind indexes. These indexes can be used to perform searches on encrypted data. The indexes themselves are unreadable by humans.\n\nOur package is a wrapper over CipherSweet, which allows you to easily use it with Laravel's Eloquent models.\n\n## Support us\n\n[\u003cimg src=\"https://github-ads.s3.eu-central-1.amazonaws.com/laravel-ciphersweet.jpg?t=1\" width=\"419px\" /\u003e](https://spatie.be/github-ad-click/laravel-ciphersweet)\n\nWe invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).\n\nWe highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).\n\n## Installation\n\nYou can install the package via composer:\n\n```bash\ncomposer require spatie/laravel-ciphersweet\n```\n\nYou must publish and run the migrations with:\n\n```bash\nphp artisan vendor:publish --tag=\"ciphersweet-migrations\"\nphp artisan migrate\n```\n\nOptionally, you can publish the config file with:\n\n```bash\nphp artisan vendor:publish --tag=\"ciphersweet-config\"\n```\n\nThis is the contents of the config file:\n\n```php\nreturn [\n    /*\n     * This controls which cryptographic backend will be used by CipherSweet.\n     * Unless you have specific compliance requirements, you should choose\n     * \"nacl\".\n     *\n     * Supported: \"boring\", \"fips\", \"nacl\"\n     */\n\n    'backend' =\u003e env('CIPHERSWEET_BACKEND', 'nacl'),\n\n    /*\n     * Select which key provider your application will use. The default option\n     * is to read a string literal out of .env, but it's also possible to\n     * provide the key in a file or use random keys for testing.\n     *\n     * Supported: \"file\", \"random\", \"string\"\n     */\n\n    'provider' =\u003e env('CIPHERSWEET_PROVIDER', 'string'),\n\n    /*\n     * Set provider-specific options here. \"string\" will read the key directly\n     * from your .env file. \"file\" will read the contents of the specified file\n     * to use as your key. \"custom\" points to a factory class that returns a\n     * provider from its `__invoke` method. Please see the docs for more details.\n     */\n    'providers' =\u003e [\n        'file' =\u003e [\n            'path' =\u003e env('CIPHERSWEET_FILE_PATH'),\n        ],\n        'string' =\u003e [\n            'key' =\u003e env('CIPHERSWEET_KEY'),\n        ],\n    ],\n    \n    /*\n     * The provided code snippet checks whether the $permitEmpty property is set to false\n     * for a given field. If it is not set to false, it throws an EmptyFieldException indicating\n     * that the field is not defined in the row. This ensures that the code enforces the requirement for\n     * the field to have a value and alerts the user if it is empty or undefined.\n     * Supported: \"true\", \"false\"\n     */\n    'permit_empty' =\u003e env('CIPHERSWEET_PERMIT_EMPTY', FALSE)\n\n];\n```\n\n## Usage\n\nFew steps are involved to store encrypted values. Let's go through them.\n\n### 1. Preparing your model and choosing the attributes that should be encrypted\n\nAdd the `CipherSweetEncrypted` interface and `UsesCipherSweet` trait to the model that you want to add encrypted fields to.\n\nYou'll need to implement the `configureCipherSweet` method to configure CipherSweet.\n\n```php\nuse Spatie\\LaravelCipherSweet\\Contracts\\CipherSweetEncrypted;\nuse Spatie\\LaravelCipherSweet\\Concerns\\UsesCipherSweet;\nuse ParagonIE\\CipherSweet\\EncryptedRow;\nuse ParagonIE\\CipherSweet\\BlindIndex;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass User extends Model implements CipherSweetEncrypted\n{\n    use UsesCipherSweet;\n    \n    /**\n     * Encrypted Fields\n     *\n     * Each column that should be encrypted should be added below. Each column\n     * in the migration should be a `text` type to store the encrypted value.\n     *\n     * ```\n     * -\u003eaddField('column_name')\n     * -\u003eaddBooleanField('column_name')\n     * -\u003eaddIntegerField('column_name')\n     * -\u003eaddTextField('column_name')\n     * ```\n     *\n     * Optional Fields\n     * \n     * These do not encrypt when NULL is provided as a value.\n     * Instead, they become an unencrypted NULL.\n     * \n     * ```\n     * -\u003eaddOptionalTextField('column_name')\n     * -\u003eaddOptionalBooleanField('column_name')\n     * -\u003eaddOptionalFloatField('column_name')\n     * -\u003eaddOptionalIntegerField('column_name')\n     * ```\n     * \n     * A JSON array can be encrypted as long as the key structure is defined in\n     * a field map. See the docs for details on defining field maps.\n     *\n     * ```\n     * -\u003eaddJsonField('column_name', $fieldMap)\n     * ```\n     *\n     * Each field that should be searchable using an exact match needs to be\n     * added as a blind index. Partial search is not supported. See the docs\n     * for details on bit sizes and how to use compound indexes.\n     *\n     * ```\n     * -\u003eaddBlindIndex('column_name', new BlindIndex('column_name_index'))\n     * ```\n     *\n     * @see https://github.com/spatie/laravel-ciphersweet\n     * @see https://ciphersweet.paragonie.com/\n     * @see https://ciphersweet.paragonie.com/php/blind-index-planning\n     * @see https://github.com/paragonie/ciphersweet/blob/master/src/EncryptedRow.php\n     *\n     * @param EncryptedRow $encryptedRow\n     *\n     * @return void\n     */\n    public static function configureCipherSweet(EncryptedRow $encryptedRow): void\n    {\n        $encryptedRow\n            -\u003eaddField('email')\n            -\u003eaddBlindIndex('email', new BlindIndex('email_index'));\n    }\n}\n```\n\nThe example above will encrypt the `email` field on the `User` model. It also adds a blind index in the `blind_indexes` table which allows you to search on it.\n\n[Check out the CipherSweet PHP docs](https://ciphersweet.paragonie.com/php) for more information on what is possible.\n\n### 2. Generating the encrypting key\n\nAn encryption key is used to encrypt your values.  You can generate a new CipherSweet encrypting key using this command:\n\n```bash\nphp artisan ciphersweet:generate-key\n```\n\n### 3. Updating your .env file\n\nAfter the key has been generated, you should add the generated CipherSweet key to your .env file.\n\n```text\nCIPHERSWEET_KEY=\u003cYOUR-KEY\u003e\n```\n\nThe key will be used by your application to manage encrypted values.\n\n### 4. Encrypting model attributes\n\nWith this in place, you can run this command to encrypt all values:\n\n```bash\nphp artisan ciphersweet:encrypt \u003cyour-model-class\u003e \u003cgenerated-key\u003e\n```\n\nThe command will update all the encrypted fields and blind indexes of the model.\n\nIf you have a lot of rows, this process can take a long time. The command is restartable: it can be re-run without needing to re-encrypt already rotated keys.\n\n\n### Searching on blind indexes\n\nEven though values are encrypted, you can still search them using a blind index. The blind indexes will have been built up when you ran the command to encrypt the model values.\n\nThis package provides a `whereBlind` and `orWhereBlind` scope to search on blind indexes.\n\nThe first parameter is the column, the second the index name you set up when calling `-\u003eaddBlindIndex`, the third is the raw value, the package will automatically apply any transformations and hash the value to search on the blind index.\n\n```php\n$user = User::whereBlind('email', 'email_index', 'rias@spatie.be');\n```\n\n### Rotating keys\n\nShould you suspect that somebody got a hold of your encrypting key, you can re-encrypt the values. Simply generate another encrypting key, and run the `php artisan ciphersweet:encrypt` command again.\n\n```bash\nphp artisan ciphersweet:encrypt \"App\\User\" \u003cyour-new-key\u003e\n```\n\nThis will update all the encrypted fields and blind indexes of the model. Once this is done, you can update your environment or config file to use the new key.\n\n## Encrypted Unique Validation Rule\n\nYou can validate encrypted fields for uniqueness using `EncryptedUniqueRule`.\n\nWhen working with encrypted fields and blind indexes, Laravel’s default `Rule::unique()` validation doesn't work out of the box. This package includes a custom rule to check for uniqueness via blind indexes.\n\n### Usage\n\nYou may use the rule directly:\n\n```php\nuse Spatie\\LaravelCipherSweet\\Rules\\EncryptedUniqueRule;\n\n$request-\u003evalidate([\n    'email' =\u003e [new EncryptedUniqueRule(User::class, 'email_index')],\n]);\n```\n\nOr, for a more expressive approach, use the macro added to Laravel’s `Rule` class:\n\n```php\nuse Illuminate\\Validation\\Rule;\n\n$request-\u003evalidate([\n    'email' =\u003e [Rule::encryptedUnique(User::class, 'email_index')],\n]);\n```\n\n\u003e The third parameter of the rule is the database column name. If not provided, it will default to the validation attribute name (i.e., `email` in the example above).\n\n### Ignoring a Record (e.g. on update)\n\nYou can skip a specific record by using the `ignore()` method:\n\n```php\nRule::encryptedUnique(User::class, 'email_index')-\u003eignore($user-\u003eid)\n```\n\nOr pass the model instance:\n\n```php\nRule::encryptedUnique(User::class, 'email_index')-\u003eignoreModel($user)\n```\n\n\u003e 💡 Ensure the target model implements `Spatie\\LaravelCipherSweet\\Contracts\\CipherSweetEncrypted` and defines the appropriate blind index.\n\n\n## Implementing a custom backend\n\nYou can implement a custom backend by setting the `ciphersweet.backend` config value to `custom`.\n\nThe `ciphersweet.backend.custom` config value must then be set to an invokeable factory class that returns an implementation of `ParagonIE\\CipherSweet\\Contract\\BackendInterface`\n\n```php\nclass CustomBackendFactory {\n    public function __invoke()\n    {\n        return new CustomBackend();\n    }\n}\n\nclass CustomBackend implements BackendInterface {\n\n    public function encrypt(string $plaintext, SymmetricKey $key, string $aad = ''): string\n    {\n        // Your logic here.\n    }\n\n    public function decrypt(string $ciphertext, SymmetricKey $key, string $aad = ''): string\n    {\n        // Your logic here.\n    }\n\n    public function blindIndexFast(string $plaintext, SymmetricKey $key, ?int $bitLength = null): string\n    {\n        // Your logic here.\n    }\n\n    public function blindIndexSlow(string $plaintext, SymmetricKey $key, ?int $bitLength = null, array $config = []): string\n    {\n        // Your logic here.\n    }\n\n    public function getIndexTypeColumn(string $tableName, string $fieldName, string $indexName): string\n    {\n        // Your logic here.\n    }\n\n    public function deriveKeyFromPassword(string $password, string $salt): SymmetricKey\n    {\n        // Your logic here.return new SymmetricKey('123');\n    }\n\n    public function doStreamDecrypt($inputFP, $outputFP, SymmetricKey $key, int $chunkSize = 8192, ?AAD $aad = null): bool\n    {\n        // Your logic here.\n    }\n\n    public function doStreamEncrypt($inputFP, $outputFP, SymmetricKey $key, int $chunkSize = 8192, string $salt = Constants::DUMMY_SALT, ?AAD $aad = null): bool\n    {\n        // Your logic here.\n    }\n\n    public function getFileEncryptionSaltOffset(): int\n    {\n        // Your logic here.\n    }\n\n    public function getPrefix(): string\n    {\n        // Your logic here.\n    }\n}\n```\n\n## Implementing a custom key provider\n\nYou can implement a custom key provider by setting the `ciphersweet.provider` config value to `custom`.\n\nThe `ciphersweet.providers.custom` config value must then be set to an invokeable factory class that returns an implementation of `ParagonIE\\CipherSweet\\Contract\\KeyProviderInterface`  \n\n```php\nclass CustomKeyProviderFactory {\n    public function __invoke()\n    {\n        return new CustomKeyProvider();\n    }\n}\n\nclass CustomKeyProvider implements KeyProviderInterface {\n\n    public function getSymmetricKey(): SymmetricKey\n    {\n        return new SymmetricKey(''); // Your logic here.\n    }\n}\n```\n\n## Testing\n\n```bash\ncomposer test\n```\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.\n\n## Contributing\n\nPlease see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.\n\n## Security Vulnerabilities\n\nPlease review [our security policy](../../security/policy) on how to report security vulnerabilities.\n\n## Credits\n\n- [Rias Van der Veken](https://github.com/riasvdv)\n- [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspatie%2Flaravel-ciphersweet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspatie%2Flaravel-ciphersweet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspatie%2Flaravel-ciphersweet/lists"}