PHPackages                             kyzegs/doctrine-encryption-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. kyzegs/doctrine-encryption-bundle

ActiveSymfony-bundle[Database &amp; ORM](/categories/database)

kyzegs/doctrine-encryption-bundle
=================================

Doctrine field encryption and blind indexes for Symfony applications.

v1.1.0(1mo ago)16MITPHPPHP &gt;=8.2

Since Jun 22Pushed 1mo agoCompare

[ Source](https://github.com/Kyzegs/doctrine-encryption-bundle)[ Packagist](https://packagist.org/packages/kyzegs/doctrine-encryption-bundle)[ Docs](https://github.com/kyzegs/doctrine-encryption-bundle)[ GitHub Sponsors](https://github.com/kyzegs)[ RSS](/packages/kyzegs-doctrine-encryption-bundle/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (1)Dependencies (10)Versions (5)Used By (0)

[![Doctrine Encryption Bundle banner](banner.svg)](banner.svg)

Doctrine Encryption Bundle
==========================

[](#doctrine-encryption-bundle)

Field-level authenticated encryption and blind indexes for Doctrine entities in Symfony applications.

Maintained fork published as `kyzegs/doctrine-encryption-bundle`, replacing the unmaintained original package.

Requirements
------------

[](#requirements)

- PHP 8.2 or newer
- Symfony 6.4, 7.4, or 8.x
- Doctrine ORM 2.20 or 3.x
- OpenSSL with AES-256-GCM support

Installation
------------

[](#installation)

```
composer require kyzegs/doctrine-encryption-bundle
```

Register the bundle if Symfony Flex has not already done so:

```
// config/bundles.php
return [
    Kyzegs\DoctrineEncryptionBundle\DoctrineEncryptionBundle::class => ['all' => true],
];
```

Generate a 256-bit key:

```
bin/console encrypt:genkey
```

Store the result in a secret manager or an uncommitted environment file:

```
DOCTRINE_ENCRYPTION_ENCRYPT_KEY=base64-encoded-key
DOCTRINE_ENCRYPTION_BLIND_INDEX_KEY=a-different-secret
```

Configure the bundle:

```
# config/packages/doctrine_encryption.yaml
doctrine_encryption:
    encrypt_key: '%env(DOCTRINE_ENCRYPTION_ENCRYPT_KEY)%'
    blind_index_key: '%env(DOCTRINE_ENCRYPTION_BLIND_INDEX_KEY)%'
    key_id: '2026-01'
```

The encryption and blind-index keys should be different. Never commit either key.

Encrypting fields
-----------------

[](#encrypting-fields)

Use the PHP attribute on a Doctrine string field. Allow room for the versioned ciphertext envelope; `TEXT` is the least surprising choice.

```
use Doctrine\ORM\Mapping as ORM;
use Kyzegs\DoctrineEncryptionBundle\Attribute\Encrypted;

#[ORM\Column(type: 'text', nullable: true)]
#[Encrypted]
private ?string $personalNumber = null;
```

New values are written with AES-256-GCM in a versioned, authenticated envelope. The entity contains plaintext while it is in memory; Doctrine stores ciphertext. Existing unversioned AES-CBC and AES-GCM values from older bundle versions remain readable.

External XML, YAML, or PHP Doctrine mappings can opt in without modifying the entity:

```

        true

```

The equivalent field option is `encrypted: true`.

Encrypted scalar properties inside Doctrine embeddables are supported. Mark the embeddable property normally; bundle uses Doctrine's nested field path for encryption, decryption, change tracking, and database maintenance:

```
#[ORM\Embeddable]
final class ContactDetails
{
    #[ORM\Column(type: 'text')]
    #[Encrypted]
    public string $privateNote;
}
```

Searching encrypted values
--------------------------

[](#searching-encrypted-values)

Randomized encryption cannot be queried by plaintext and must not carry a meaningful unique constraint. Add a blind-index column instead:

```
use Kyzegs\DoctrineEncryptionBundle\Attribute\BlindIndex;
use Kyzegs\DoctrineEncryptionBundle\Attribute\Encrypted;

#[ORM\Column(type: 'text')]
#[Encrypted]
private string $email;

#[ORM\Column(type: 'string', length: 64, unique: true, nullable: true)]
#[BlindIndex(sourceField: 'email', normalizer: BlindIndex::NORMALIZE_LOWERCASE)]
private ?string $emailLookupHash = null;
```

Create the same hash when querying:

```
use Kyzegs\DoctrineEncryptionBundle\Hashers\BlindIndexHasherInterface;

$hash = $blindIndexHasher->hash($email, BlindIndex::NORMALIZE_LOWERCASE);
$user = $repository->findOneBy(['emailLookupHash' => $hash]);
```

Available normalizers are `none`, `trim`, `lowercase`, and `uppercase`. Blind indexes reveal equality patterns; use them only for fields that genuinely need lookups.

Rebuild indexes in bounded batches:

```
bin/console encrypt:blind-index --batch-size=500 --dry-run
bin/console encrypt:blind-index --batch-size=500
```

Key rotation
------------

[](#key-rotation)

Change the current key and key ID, then retain old keys under `decryption_keys`:

```
doctrine_encryption:
    encrypt_key: '%env(DOCTRINE_ENCRYPTION_ENCRYPT_KEY_2026)%'
    key_id: '2026'
    decryption_keys:
        '2025': '%env(DOCTRINE_ENCRYPTION_ENCRYPT_KEY_2025)%'
```

Back up the database, inspect the operation, and rotate in batches:

```
bin/console encrypt:database rotate --dry-run
bin/console encrypt:database rotate --batch-size=250
```

Remove a retired key only after every value using its key ID has been rotated and verified.

Database maintenance
--------------------

[](#database-maintenance)

The maintenance command supports `encrypt`, `decrypt`, and `rotate`, custom and composite scalar identifiers, quoted identifiers, transactions, batches, confirmation, and dry runs:

```
bin/console encrypt:database encrypt --dry-run
bin/console encrypt:database decrypt --manager=tenant --batch-size=100
```

Association identifiers are rejected because they cannot be updated safely by the low-level command. Always take a verified backup before a write operation.

Multiple Doctrine connections
-----------------------------

[](#multiple-doctrine-connections)

```
doctrine_encryption:
    encrypt_key: '%env(DOCTRINE_ENCRYPTION_ENCRYPT_KEY)%'
    connections: ['default', 'tenant']
```

Optional Twig filter
--------------------

[](#optional-twig-filter)

Install Twig and leave `enable_twig` enabled to expose `value|decrypt`:

```
composer require symfony/twig-bundle
```

Decrypting in templates increases the number of places where plaintext exists. Prefer decrypting only at the application boundary that needs it.

Custom integrations
-------------------

[](#custom-integrations)

`KeyProviderInterface` is the extension point for Vault, KMS, HSM, or another secret source. It returns binary 32-byte keys and supports lookup by ciphertext key ID. Register the implementation as a service and configure it directly:

```
doctrine_encryption:
    key_provider_service: 'App\\Encryption\\KmsKeyProvider'
    blind_index_key: '%env(DOCTRINE_ENCRYPTION_BLIND_INDEX_KEY)%'
```

Likewise, `encryptor_service` accepts any registered `EncryptorInterface` service with arbitrary injected dependencies. `encryptor_class` remains available as a deprecated compatibility path for classes using the historical event-dispatcher constructor.

Security notes
--------------

[](#security-notes)

- Encryption does not replace access control, TLS, backups, audit logging, or database hardening.
- Losing an encryption key permanently loses the corresponding data.
- Application compromise can expose plaintext and keys while the process is running.
- Blind indexes permit equality analysis and should use a separate high-entropy secret.
- Test restoration and rotation on a copy of production data before operating on production.

See [UPGRADE.md](UPGRADE.md) before upgrading an existing installation and [SECURITY.md](SECURITY.md) for vulnerability reporting.

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance91

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community17

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 68.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

2

Last Release

44d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/eb13f61de13b186245a047cd1d882784e4dacb5b9f2a8f930b20e5992159e61a?d=identicon)[Kyzegs](/maintainers/Kyzegs)

---

Top Contributors

[![mogilvie](https://avatars.githubusercontent.com/u/7894754?v=4)](https://github.com/mogilvie "mogilvie (103 commits)")[![Lpsd](https://avatars.githubusercontent.com/u/40902730?v=4)](https://github.com/Lpsd "Lpsd (14 commits)")[![Kyzegs](https://avatars.githubusercontent.com/u/45851377?v=4)](https://github.com/Kyzegs "Kyzegs (11 commits)")[![danabrey](https://avatars.githubusercontent.com/u/10567440?v=4)](https://github.com/danabrey "danabrey (3 commits)")[![tsiatka](https://avatars.githubusercontent.com/u/47247055?v=4)](https://github.com/tsiatka "tsiatka (2 commits)")[![David-Dadon](https://avatars.githubusercontent.com/u/180660987?v=4)](https://github.com/David-Dadon "David-Dadon (2 commits)")[![raulpuente](https://avatars.githubusercontent.com/u/6062825?v=4)](https://github.com/raulpuente "raulpuente (2 commits)")[![Seros](https://avatars.githubusercontent.com/u/9016208?v=4)](https://github.com/Seros "Seros (2 commits)")[![FournyP](https://avatars.githubusercontent.com/u/64586968?v=4)](https://github.com/FournyP "FournyP (1 commits)")[![feymo](https://avatars.githubusercontent.com/u/60115888?v=4)](https://github.com/feymo "feymo (1 commits)")[![TravisMarkvh](https://avatars.githubusercontent.com/u/62843006?v=4)](https://github.com/TravisMarkvh "TravisMarkvh (1 commits)")[![Rindula](https://avatars.githubusercontent.com/u/20195655?v=4)](https://github.com/Rindula "Rindula (1 commits)")[![russelomua](https://avatars.githubusercontent.com/u/313658?v=4)](https://github.com/russelomua "russelomua (1 commits)")[![brysn](https://avatars.githubusercontent.com/u/3696643?v=4)](https://github.com/brysn "brysn (1 commits)")[![spacecodeit](https://avatars.githubusercontent.com/u/25511964?v=4)](https://github.com/spacecodeit "spacecodeit (1 commits)")[![tismaximo](https://avatars.githubusercontent.com/u/119903808?v=4)](https://github.com/tismaximo "tismaximo (1 commits)")[![TonySma](https://avatars.githubusercontent.com/u/6605868?v=4)](https://github.com/TonySma "TonySma (1 commits)")[![joelterry-promenade](https://avatars.githubusercontent.com/u/106996220?v=4)](https://github.com/joelterry-promenade "joelterry-promenade (1 commits)")[![jdecool](https://avatars.githubusercontent.com/u/433926?v=4)](https://github.com/jdecool "jdecool (1 commits)")

---

Tags

symfonyencryptiondoctrineblind-index

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/kyzegs-doctrine-encryption-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/kyzegs-doctrine-encryption-bundle/health.svg)](https://phpackages.com/packages/kyzegs-doctrine-encryption-bundle)
```

###  Alternatives

[rcsofttech/audit-trail-bundle

Enterprise-grade, high-performance Symfony audit trail bundle. Automatically track Doctrine entity changes with split-phase architecture, multiple transports (HTTP, Queue, Doctrine), and sensitive data masking.

12017.1k](/packages/rcsofttech-audit-trail-bundle)[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k18.3M414](/packages/easycorp-easyadmin-bundle)[kimai/kimai

Kimai - Time Tracking

4.8k9.4k1](/packages/kimai-kimai)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M223](/packages/sulu-sulu)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1617.3k14](/packages/2lenet-crudit-bundle)[ahmed-bhs/doctrine-doctor

Runtime analysis tool for Doctrine ORM integrated into Symfony Web Profiler. Unlike static linters, it analyzes actual query execution at runtime to detect performance bottlenecks, security vulnerabilities, and best practice violations during development with real execution context and data.

12411.1k](/packages/ahmed-bhs-doctrine-doctor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
