caeligo/field-encryption-bundle

A Symfony bundle for transparent Doctrine entity field encryption using AES-256-CBC

Maintainers

Package info

github.com/biga156/field-encryption-bundle

Type:symfony-bundle

pkg:composer/caeligo/field-encryption-bundle

Statistics

Installs: 17

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.4.0 2026-03-21 16:43 UTC

This package is auto-updated.

Last update: 2026-03-21 16:43:57 UTC


README

A Symfony bundle for transparent Doctrine entity field encryption using AES-256-CBC for string fields and AES-256-GCM for binary files.

PHP Symfony License

Features

  • ๐Ÿ” Automatic encryption/decryption - Transparent for your application code
  • ๐Ÿ“ String field encryption - AES-256-CBC with HMAC-SHA256 hash for searching
  • ๐Ÿ“ Binary file encryption - AES-256-GCM for documents, images, etc.
  • ๐Ÿ”‘ HKDF key derivation - Cryptographic key separation for different purposes
  • ๐Ÿ›ก๏ธ Timing-safe comparison - Protection against timing attacks on hash verification
  • ๐Ÿท๏ธ Attribute-based configuration - Simple #[Encrypted] and #[EncryptedFile] attributes
  • ๐Ÿ”„ Key rotation support - Safely rotate keys with progress tracking
  • ๐Ÿ—œ๏ธ Optional compression - Gzip compression for binary files
  • ๐Ÿ“‹ Metadata storage - Store MIME type, filename, size alongside encrypted content
  • ๐Ÿ› ๏ธ Console commands - Key generation, rotation wizard, data migration

Requirements

  • PHP 8.2+
  • Symfony 6.4+ or 7.x
  • Doctrine ORM 2.14+ or 3.x

Installation

composer require caeligo/field-encryption-bundle

Register the bundle in config/bundles.php:

return [
    // ...
    Caeligo\FieldEncryptionBundle\FieldEncryptionBundle::class => ['all' => true],
];

Quick Start

1. Generate Encryption Key

php bin/console field-encryption:generate-key --append-to-env

2. Configure the Bundle

# config/packages/field_encryption.yaml
field_encryption:
    encryption_key: '%env(FIELD_ENCRYPTION_KEY)%'

3. Add Attributes to Your Entity

use Caeligo\FieldEncryptionBundle\Attribute\Encrypted;
use Caeligo\FieldEncryptionBundle\Attribute\EncryptedEntity;

#[ORM\Entity]
#[EncryptedEntity]
class User
{
    #[ORM\Column(type: Types::TEXT, nullable: true)]
    #[Encrypted(hashField: true, hashProperty: 'emailHash')]
    private ?string $email = null;

    #[ORM\Column(type: Types::TEXT, nullable: true, unique: true)]
    private ?string $emailHash = null;

    private ?string $plainEmail = null;  // Transient, auto-populated

    public function getEmail(): ?string
    {
        return $this->plainEmail;
    }

    public function setEmail(?string $email): self
    {
        $this->plainEmail = $email;
        return $this;
    }
}

That's it! The bundle automatically encrypts on save and decrypts on load.

Documentation

Document Description
String Encryption Encrypting text fields (emails, names, etc.)
File Encryption Encrypting binary files (documents, images)
Console Commands Key generation, rotation, migration commands
Key Rotation Safely rotating encryption keys
Configuration Complete configuration reference

Basic Examples

Encrypted String Field

#[Encrypted(hashField: true)]
private ?string $email = null;

private ?string $plainEmail = null;
private ?string $emailHash = null;

Encrypted File Field

use Caeligo\FieldEncryptionBundle\Attribute\EncryptedFile;
use Caeligo\FieldEncryptionBundle\Model\EncryptedFileData;

#[EncryptedFile(mimeTypeProperty: 'mimeType', originalNameProperty: 'fileName')]
private $document;

private ?EncryptedFileData $plainDocument = null;
private ?string $mimeType = null;
private ?string $fileName = null;

Working with Files

// From upload
$fileData = EncryptedFileData::fromUploadedFile($uploadedFile);
$entity->setPlainDocument($fileData);

// To download
$content = $entity->getPlainDocument()->getContent();
$mimeType = $entity->getPlainDocument()->getMimeType();

Console Commands

# Generate new encryption key
php bin/console field-encryption:generate-key

# Rotate encryption keys (interactive wizard)
php bin/console field-encryption:rotate-keys --wizard

# Encrypt existing unencrypted data
php bin/console field-encryption:encrypt-existing --dry-run

Security Considerations

  • โš ๏ธ Never commit encryption keys - Use environment variables
  • ๐Ÿ’พ Backup your keys - Key loss = data loss
  • ๐Ÿ”„ Plan key rotation - Use the wizard for safe rotation
  • ๐Ÿ” Use hashes for search - Enable hashField for searchable fields
  • ๐Ÿ†” Use ULID/UUID - Don't use sequential integers for key derivation
  • ๐ŸŒถ๏ธ Consider hash pepper - Use hash_pepper config for extra key separation

Database Compromise Protection

This bundle provides strong protection if only your database is compromised:

Attacker sees Can read? Notes
Encrypted fields โŒ No AES-256 encrypted
Hash fields โš ๏ธ Hash only HMAC-SHA256, not reversible
Plain metadata โœ… Yes Store sensitive metadata separately

Key requirement: The encryption key must NOT be stored in the database.

License

MIT License - see LICENSE

Author

Bรญrรณ Gรกbor (@biga156)

Repository