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 Ciphersweet Encryption Bundle Laravel Package

odandb/doctrine-ciphersweet-encryption-bundle

A Doctrine bundle that adds CipherSweet field-level encryption to your entities, letting you store sensitive data encrypted while keeping it searchable through blind indexes. Attribute-based config makes setup simple and secure.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a Symfony bundle, not a Laravel package — it wires CipherSweet field-level encryption into Doctrine ORM entities via Doctrine event subscribers (onFlush/postLoad/postFlush). The underlying crypto (CipherSweet, blind indexes, key provider) is framework-agnostic, but the delivery mechanism is Symfony's bundle + DI container. For a Laravel-first estate this is an integration project, not a composer require. For a Symfony or mixed Symfony/Doctrine service, it fits cleanly into existing entity lifecycles with no application-layer code changes for basic encrypted fields.

Integration feasibility. Feasible for greenfield and for services already using Doctrine attributes for encrypted fields. The real effort is not installing the bundle; it is the surrounding work:

Workstream Effort Notes
Key management High CipherSweet needs a KeyProvider; must decide on KMS/envelope encryption, rotation policy, per-tenant keys
Blind index design Medium–High Every searchable/filterable/unique field needs a blind index + schema column; this constrains future query design
Schema/column sizing Medium Ciphertext + blind index columns expand row size; affects indexes, sort order, uniqueness
Data migration High Existing plaintext rows must be encrypted backfill-style; dual-read/dual-write window required
Query audit Medium Any WHERE/ORDER BY/LIKE on encrypted fields breaks silently or errors; must be enumerated up front

Technical risk. Version 0.13.0 is a 0.x pre-1.0 release with no BC guarantees. Two changes carry real, if moderate, risk:

  1. symfony/property-info → symfony/type-info. This is the component used to resolve entity property types so the bundle knows how to encrypt/decrypt a field. Swapping the type-resolution engine is a behaviorally sensitive change: type inference edge cases (nullable, union types, typed collections, custom Doctrine types, inherited properties) are exactly where encryption silently mis-applies or throws at runtime. symfony/type-info is a newer component with a PHP 8.2+ floor and a different maturity curve than property-info. Expect a possible jump in minimum PHP/Symfony constraints — verify composer.json before committing.
  2. "Remove ORM deprecation" (PR #33). This reads as Doctrine ORM 3 compatibility work. Confirm whether ORM 2 is still supported; if the deprecation removal is ORM-3-only API usage, projects on ORM 2.x may break on upgrade.

Additional risks: no documented migration/upgrade notes in the changelog; a single maintainer handles both PRs (bus factor); and encrypted-data packages are not forgiving of regressions — a decryption bug is a data-integrity incident, not a UI bug.

Key questions for the maintainer / vendor.

  • What are the new composer.json constraints — minimum PHP, Symfony, and Doctrine ORM versions? Is ORM 2.x still supported?
  • Is the type-info swap behaviorally identical for nullable, union, inherited, and custom-Doctrine-type properties? Any known edge cases?
  • Does upgrading require re-encrypting or otherwise touching existing ciphertext, or is it read-compatible with 0.12.x data?
  • Is there a 1.0 roadmap / BC policy commitment, and what's the security disclosure process?
  • Test coverage and CI matrix for the encryption round-trip and blind-index correctness?

Recommendation: adoptable for a Symfony/Doctrine service with a named owner and a staging round-trip test; not a drop-in for a Laravel codebase without a wrapper decision. Treat 0.13.0 as a pinned dependency, not a floating ^0.13.

Integration Approach

Stack fit. Determine first which of three situations you're in:

Situation Path
Symfony + Doctrine service Native fit — install bundle, configure KeyProvider, annotate entities
Laravel + Eloquent service No fit. Use paragonie/ciphersweet directly in model casts/mutators, or a Laravel encryption package; this bundle will not help
Laravel + Doctrine (e.g. via a Doctrine bridge) Possible but off the happy path; register the subscriber manually and own the wiring

Do not let "it's a PHP package" collapse these into one decision — the install instructions and the support burden are different in each.

Migration path. For existing plaintext data, sequence a controlled backfill rather than a big-bang cutover:

  1. Add ciphertext + blind-index columns alongside existing plaintext columns.
  2. Deploy dual-write (write plaintext and ciphertext), reads still from plaintext.
  3. Backfill historical rows in batches; verify round-trip decryption and blind-index query parity per batch.
  4. Flip reads to ciphertext; keep plaintext for a defined soak period (2–4 weeks minimum).
  5. Drop plaintext columns and revoke access to the plaintext backups.

For greenfield, skip 1–4 but still validate blind-index query patterns against the product's actual search requirements before schema freeze — this is the most common source of rework.

Compatibility. Because 0.13.0 changes type resolution, pin exactly and test the upgrade in a branch:

  • Run a full encrypt→persist→reload→decrypt round-trip suite against a copy of production-shaped data.
  • Explicitly cover nullable fields, union/typed properties, embedded/embedded-array values, and any custom Doctrine types.
  • Verify PHP and Symfony version constraints against your runtime matrix before merging; expect a possible PHP 8.2 floor.
  • Check that ORM 3 deprecation removal didn't raise your minimum ORM version.

If your platform is still on PHP 8.1 or Symfony 6.3-or-earlier, this release may simply be unavailable to you — confirm before planning the sprint.

Sequencing.

  1. Confirm Laravel vs. Symfony fit (kill criterion).
  2. Resolve the key-management design — this gates everything and is the longest lead item.
  3. Enumerate all queries touching fields destined for encryption; design blind indexes.
  4. Upgrade/pin the bundle in staging and run the round-trip suite.
  5. Build the dual-write + backfill tooling.
  6. Roll out per service, plaintext-first, then flip reads.

Rough sizing for a mid-size service: 1–2 sprints for greenfield with clean queries; 3–5 sprints for a migration with existing searchable data and key-management build-out.

Operational Impact

Maintenance. At 0.x with a single active maintainer and two commits in this release, expect to own the upgrade cadence yourself — budget a recurring dependency-review slot each release rather than assuming upstream will carry compatibility. Pin exact versions and upgrade deliberately; never float the constraint on a package that sits in the data-integrity path.

Support. Internal expertise must exist for both halves: CipherSweet (key providers, blind indexes, ciphertext formats) and Doctrine's event lifecycle. There is no realistic path to "the framework team supports it." Name a single owning team and an escalation contact. Also establish an exit plan — because ciphertext is written into your database, you cannot casually swap this package out; the cost of replacing it is a full decrypt-and-re-encrypt migration. Factor that lock-in into the initial decision.

Scaling.

  • Write throughput: encryption + blind-index computation on every flushed entity adds per-write CPU. Measure on your hot paths; batch imports and bulk updates are the usual pain points.
  • Reads: decryption is per-row and CPU-bound — fine for OLTP, hostile to large exports and analytics. Encrypted fields are effectively invisible to reporting/BI; plan a separate projection or warehouse path.
  • Indexes: blind indexes support equality and exact-match prefix search only. Range queries, sorting, LIKE, and aggregate-by-encrypted-field are gone. This is a product constraint, not just a technical one — surface it to whoever owns search and reporting before, not after, commit.
  • Storage: ciphertext plus blind index columns inflate row size; re-check index bloat and backup windows.

Failure modes. Rank by severity:

Failure Impact Mitigation
Lost/rotated-wrong key Catastrophic — ciphertext unrecoverable KMS, envelope encryption, encrypted backups, tested restore drill
Decryption regression after upgrade Runtime errors or silent garbage on read Round-trip test suite in CI against production-shaped data; staged rollout
Query on encrypted field Broken search or errors in production Pre-merge query audit; automated detection of queries against encrypted columns
Mis-typed property skipped by encryption Silent plaintext leakage — worst case, invisible Assert-on-write that expected fields are non-plaintext; spot audits; test matrix covering nullable/union/embedded properties
Blind-index drift (key change without reindex) Searches silently return no results Tie index keys to key version; reindex on rotation
Migration half-complete Mixed plaintext/ciphertext rows Idempotent backfill + completeness check before dropping plaintext

The silent-plaintext-leakage row is the one to design around explicitly. It produces no error, no alert, and no user complaint — only a compliance finding months later.

Ramp-up. Allocate roughly two to three weeks for a competent engineer to become productive, split across CipherSweet concepts (blind indexes, key providers, ciphertext format), Doctrine event-subscriber behavior and its flush-ordering subtleties, and the key-management runbook. The encryption model is the easy part; the operational discipline around keys and migration is what takes the time. Pair this with a written runbook covering key rotation, restore-from-backup, and the "a field is unexpectedly plaintext" incident response — and rehearse the restore at least once before go-live.

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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource