nowo-tech / doctrine-encrypt-bundle
Encrypt Doctrine entity fields at rest with Halite or Defuse. Symfony 7|8 bundle for field-level encryption, GDPR-friendly, multiple keys, key rotation.
Installs: 12
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/nowo-tech/doctrine-encrypt-bundle
Requires
- php: >=8.1
- doctrine/orm: ^2.15 || ^3.0
- paragonie/halite: ^5.1
- paragonie/sodium_compat: ^1.20 || ^2.0
- symfony/config: ^7.0 || ^8.0
- symfony/dependency-injection: ^7.0 || ^8.0
- symfony/http-kernel: ^7.0 || ^8.0
- symfony/property-access: ^7.0 || ^8.0
- symfony/var-exporter: ^7.0 || ^8.0
- symfony/yaml: ^7.0 || ^8.0
- twig/twig: ^3.2
Requires (Dev)
- defuse/php-encryption: ^2.1
- friendsofphp/php-cs-fixer: ^3.0
- phpunit/phpunit: ^10.0 || ^11.0
- symfony/cache: ^7.0 || ^8.0
Suggests
- ext-sodium: Required to use Halite encryption library
- defuse/php-encryption: Alternative to Halite for encryption
README
Symfony bundle to encrypt Doctrine entity fields at rest using Halite or Defuse—audited libraries, no custom crypto. For Symfony 7 and 8 · PHP 8.1+. Suits GDPR and compliance (e.g. Art. 32); supports key rotation and Nowo\AnonymizedBundle for anonymization and erasure.
⭐ Found this useful? Install from Packagist · Give it a star on GitHub so more developers can find it.
Table of contents
- Quick search terms
- Features
- Installation
- Configuration
- Usage
- Documentation
- Requirements
- Demo
- Development
- License & author
Quick search terms
Looking for Doctrine encryption, encrypt entity fields, Halite Symfony, Defuse encryption, field-level encryption, encrypt database column, Symfony encrypt attribute, Doctrine Encrypted? You're in the right place.
Features
- ✅ Encrypt and decrypt entity properties with a single attribute
- ✅ Multiple encryptor configs — e.g.
personal_data(Halite) andfinancial_data(Defuse) in the same app, each with its own key - ✅ Halite and Defuse — audited crypto libraries, no custom algorithms
- ✅ Transparent: encrypt on persist/update, decrypt on load
- ✅ EncryptUtil — programmatic
encrypt()/decrypt()with optional config name (default or e.g.financial_data) - ✅ MaskUtil — mask sensitive values in PHP (e.g. show only last N chars); usable in services
- ✅ Twig filters —
|decrypt(decrypt in templates; optional config:{{ value|decrypt }}or{{ value|decrypt('financial_data') }}) and|mask(mask for display:{{ value|mask(4) }}or{{ value|decrypt|mask(4) }}) - ✅ Works with embedded entities and inheritance
- ✅ Console commands: status, generate secret key, encrypt/decrypt database, rotate keys (backup, decrypt, change keys, re-encrypt with confirmations)
- ✅ Key rotation — one command or manual steps; combinable with Nowo\AnonymizedBundle for GDPR-compliant anonymization and erasure
- ✅ Symfony Flex recipe (register bundle + config; see docs/INSTALLATION.md)
- ✅ Compatible with Symfony 7 and 8 and Doctrine ORM 2.x and 3.x
- ✅ Compatible with FrankenPHP (runtime and worker mode; see Installation → FrankenPHP)
Installation
composer require nowo-tech/doctrine-encrypt-bundle
With Symfony Flex, the recipe (when enabled) registers the bundle and creates the config file automatically. Without Flex, see docs/INSTALLATION.md for manual steps.
Manual registration in config/bundles.php:
<?php return [ // ... Nowo\DoctrineEncryptBundle\NowoDoctrineEncryptBundle::class => ['all' => true], ];
Configuration
Create config/packages/nowo_doctrine_encrypt.yaml. You can use one encryptor (legacy) or multiple named configs (recommended).
Multiple configs (recommended)
Use different encryptors and keys per kind of data (e.g. personal vs financial):
nowo_doctrine_encrypt: default_config: personal_data # used when attribute has no config or uses "default" configs: personal_data: encryptor_class: Halite secret_directory_path: '%kernel.project_dir%' financial_data: encryptor_class: Defuse secret_directory_path: '%kernel.project_dir%'
Defuse: composer require defuse/php-encryption ^2.1
Key files: one per config, e.g. .Halite.personal_data.key, .Defuse.financial_data.key in the config’s secret_directory_path. Add to .gitignore:
.Halite.key .Defuse.key .Halite.*.key .Defuse.*.key
Generate keys: php bin/console doctrine:encrypt:generate-secret-key (creates missing Halite/Defuse keys for all configs, or pass a config alias). See docs/CONFIGURATION.md and docs/COMMANDS.md.
Single encryptor (one config)
Use one entry under configs (e.g. default):
nowo_doctrine_encrypt: default_config: default configs: default: encryptor_class: Halite # or Defuse secret_directory_path: '%kernel.project_dir%'
Key file: .Halite.default.key (or .Defuse.default.key). Full options: docs/CONFIGURATION.md.
Usage
Mark entity properties with the Encrypted attribute. Use no argument (or "default") for the default config, or the config name when using multiple configs:
use Nowo\DoctrineEncryptBundle\Configuration\Encrypted; #[ORM\Entity] class User { #[ORM\Column(type: 'string')] #[Encrypted] // or #[Encrypted('default')] — uses default_config private ?string $email = null; }
With multiple configs, pass the config alias per property:
#[ORM\Column(type: 'string')] #[Encrypted('personal_data')] private ?string $email = null; #[ORM\Column(type: 'string')] #[Encrypted('financial_data')] private ?string $iban = null;
Values are encrypted on persist/update and decrypted on load. For programmatic use: EncryptUtil (encrypt/decrypt) and MaskUtil (mask for display). In Twig use the |decrypt and |mask filters. See docs/USAGE.md for EncryptUtil, MaskUtil, Twig filters, embedded entities, and inheritance.
Documentation
| Document | Description |
|---|---|
| Installation | Requirements, Flex and manual install, secret key, FrankenPHP (runtime & worker), IDE (optional) |
| Configuration | All options and defaults |
| Usage | Encrypted attribute, EncryptUtil, MaskUtil, Twig filters (decrypt, mask), embedded entities, inheritance |
| Example | Full example: entity, fixtures, controller, template |
| Commands | Status (per-entity properties and configs), generate key, encrypt/decrypt database, rotate keys |
| Key rotation | Strategy to change keys: backup, decrypt, replace keys, re-encrypt. Supports GDPR compliance; combinable with Nowo\AnonymizedBundle. |
| Demo | Demo projects (Symfony 7/8) and how to run them |
| Changelog | Version history |
| Upgrading | Upgrade notes between versions |
| Roadmap | Vision and future ideas |
| Security | Reporting vulnerabilities |
| Contributing | How to contribute and code style |
| Release | Release checklist (for maintainers) |
| Custom encryptor | Implement your own encryptor |
Requirements
- PHP >= 8.1
- Symfony 7 or 8 (^7.0 || ^8.0). The bundle is compatible with Symfony 7 and 8 only; for Symfony 6 use
^1.0of this bundle. - Doctrine ORM ^2.15 || ^3.0
- paragonie/halite (included); for Defuse:
defuse/php-encryption ^2.1 - ext-sodium recommended for Halite (or sodium_compat)
See docs/INSTALLATION.md and docs/UPGRADING.md for compatibility notes.
Demo
Demos for Symfony 7 and 8 are in demo/symfony7, demo/symfony8. Each runs with FrankenPHP and Caddy. Quick start: docs/DEMO.md.
Development
Run tests and QA with Docker: make up && make install && make test (or make test-coverage, make qa). Without Docker: composer install && composer test. See Makefile for all targets.
License
The MIT License (MIT). Please see LICENSE for more information.
Author
Created by Héctor Franco Aceituno at Nowo.tech