Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Doctrine Encryption Bundle Laravel Package

kyzegs/doctrine-encryption-bundle

A Symfony bundle for Doctrine ORM that adds transparent field-level encryption for sensitive entity data, with configurable encryptors to help protect information at rest while keeping mappings and application code simple.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Doctrine bundle, so in Laravel you need Doctrine present (laravel-doctrine/orm or a manual DBAL/ORM wiring) before anything here applies. Steps:

  1. composer require kyzegs/doctrine-encryption-bundle:^2.0 (note the major bump — see Gotchas before upgrading an existing install).
  2. Register the bundle with your Doctrine setup (config/bundles.php in Symfony; in Laravel, add the DBAL types and the subscriber/event hooks in config/doctrine.php).
  3. Publish/provide an encryption key. v2 expects a key material source (env var, key file, or key provider service) — never hard-code it, and never commit it.
  4. Mark your first encrypted field: annotate a Doctrine entity property with the bundle's Encrypted attribute, or declare a column as the new encrypted_text DBAL type.
  5. Run a migration to add the column plus its blind index column, flush an entity, then read it back to confirm the round trip.

First realistic use case: encrypting PII (email, phone, national ID) on a Doctrine-mapped model while still being able to query it by exact match via the blind index.

Read the upgrade doc shipped with v2.0.0 first if you have any v1.x data — it is the authoritative source on what changed in the ciphertext format.

Implementation Patterns

Attribute-driven encryption. Keep the mapping declarative: #[Encrypted] on the property, blind index declared as a sibling attribute/column. Business logic never touches encrypt/decrypt — it writes plaintext, Doctrine handles the rest on flush/hydrate.

Blind index for lookups. The new query helper (PR #3) is the headline feature. Pattern: store the HMAC-based blind index in a separate indexed column and query it through the helper rather than hand-rolling hash_hmac. Exact-match only — no LIKE, no range queries, no ordering on the encrypted value.

encrypted_text DBAL type. Use it when you want the column type itself to carry the encryption contract (useful for schema diffing and for models where attributes are awkward). Register the type in your DBAL type map before running migrations, or schema tooling will emit a plain TEXT column.

Repository/service boundaries. Wrap blind-index lookups in repository methods (findByEmail(string $email)) so callers never see the hash. This keeps key/pepper changes contained to one layer.

Migration and re-encryption workflow. v2 makes dry runs read every value. Use that as a pre-flight validation pass in staging: dry run first, inspect the report for undecryptable or malformed rows, then run for real. Wire it into a queued job for large tables rather than a request.

Integration tip. In Laravel, register the DBAL type and any event subscribers in a service provider's boot() and gate it behind config('encryption.enabled') so tests and local seeds can run unencrypted if needed.

Gotchas and Tips

  • This is a major version with data-format implications. PR #2 fixes "data-loss and ciphertext-integrity defects" — that phrasing usually means previously written ciphertext may be malformed, unauthenticated, or silently truncated. Do not assume v1.x ciphertext is readable by v2. Run the documented upgrade path and verify with a dry run before flipping production.
  • Dry runs are now expensive by design. "Make dry runs read every value" trades speed for correctness. On large tables the dry run is a full table scan with decryption — schedule it off-peak, chunk it, and don't run it as a side effect of every deploy.
  • Laravel has no first-class Doctrine. You are wiring DBAL types, event subscribers, and config by hand. If the bundle's docs assume Symfony's bundle auto-configuration, expect to translate YAML/PHP config into a service provider yourself.
  • Blind index determinism is a footgun. Same plaintext must always yield the same index. If you change the pepper/key used for the index, every existing lookup breaks. Version your index key separately from the encryption key and plan for re-indexing.
  • Key rotation is on you. The bundle encrypts/decrypts; it does not manage key history. Keep a key ID alongside ciphertext (or in the key provider) so you can decrypt old rows after rotating.
  • Column sizing. Ciphertext plus IV/tag/base64 expansion means a 255-char column for a 100-char value will fail. Size generously (TEXT) and remember index columns need their own length budget.
  • Debugging tip. When hydration fails, the exception is often a generic decryption/type error several layers from the real cause. Log the entity class and property name — not the ciphertext — and reproduce against a single row before running any bulk job.
  • Extension point. The key provider and the blind-index hasher are the two seams worth wrapping in your own implementations; that is where you inject KMS/Secrets Manager and your own pepper handling.
  • Uniqueness constraints. You cannot put a DB unique constraint on the encrypted column — put it on the blind index column, and accept that it enforces uniqueness on the hash, so hash collisions (astronomically unlikely) become constraint violations.
  • Test fixtures. Set up a test key in phpunit.xml and reset DB state between tests; encrypted attributes make raw dump/diff assertions noisy and unreadable.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager