Weave Code
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

brandoriented/doctrine-encryption-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require brandoriented/doctrine-encryption-bundle dev-master
    

    Add the bundle to AppKernel.php:

    new BrandOriented\Encryption\DoctrineEncryptionBundle(),
    
  2. Configure: Add basic encryption settings to config/packages/doctrine_encryption.yaml:

    doctrine_encryption:
      key: '%env(ENCRYPTION_KEY)%'
      iv: '%env(ENCRYPTION_IV)%'
      suffix: '_encrypted'
    
  3. First Use Case: Encrypt a field in an entity:

    use BrandOriented\Encryption\Annotation\Encrypted;
    
    class User {
        /**
         * @Encrypted()
         */
        private $sensitiveData;
    }
    

    The field will auto-encrypt on prePersist/preUpdate.


Implementation Patterns

Workflows

  1. Entity Encryption:

    • Use @Encrypted() annotation on Doctrine entity properties.
    • Encryption triggers automatically via Doctrine lifecycle events (prePersist, preUpdate).
    • Example:
      class Patient {
          /**
           * @Encrypted()
           */
          private $ssn;
      }
      
  2. Manual Encryption/Decryption:

    • Inject the Bridge service in controllers/services:
      use BrandOriented\Encryption\Bridge\Bridge;
      
      public function __construct(private Bridge $bridge) {}
      
      public function handleSensitiveData() {
          $encrypted = $this->bridge->encrypt('secret');
          $decrypted = $this->bridge->decrypt($encrypted);
      }
      
  3. Twig Integration:

    • Decrypt values in templates:
      {{ user.ssn | decrypt }}  {# Outputs decrypted SSN #}
      
  4. Custom Encryptor:

    • Override the default encryptor by configuring a custom class:
      doctrine_encryption:
        class: 'App\Service\CustomEncryptor'
      
    • Implement BrandOriented\Encryption\EncryptorInterface.

Integration Tips

  • Environment Variables: Store key and iv in .env (e.g., ENCRYPTION_KEY=your_32_byte_key). Use Symfony’s %env() in config for security.

  • Doctrine Events: Extend existing events (e.g., preFlush) for bulk operations:

    $em->getEventManager()->addEventListener(
        Doctrine\ORM\Events::preFlush,
        [$this, 'encryptAllSensitiveData']
    );
    
  • Migrations: Avoid encrypting existing data in migrations. Use raw SQL or manual decryption first.


Gotchas and Tips

Pitfalls

  1. No postLoad Handling:

    • The bundle does not decrypt data on postLoad. Fields remain encrypted in memory unless manually decrypted.
    • Workaround: Use a Doctrine listener to decrypt after postLoad:
      $em->getEventManager()->addEventListener(
          Doctrine\ORM\Events::postLoad,
          [$this, 'decryptEntityFields']
      );
      
  2. Suffix Collisions:

    • The suffix config (e.g., _encrypted) is appended to encrypted values.
    • Risk: If suffix matches existing data (e.g., user_email_encrypted vs. user_email_encrypted), decryption fails.
    • Fix: Use a unique suffix (e.g., _enc_${random_string}).
  3. Key Rotation:

    • No built-in key rotation. Manually update key/iv in config and re-encrypt data:
      php bin/console doctrine:query-sql "UPDATE users SET ssn = :encrypted WHERE 1"
      --param=encrypted: '...'  {# Newly encrypted value #}
      
  4. Performance:

    • Encryption/decryption adds overhead. Avoid encrypting large fields (e.g., JSON blobs).
    • Tip: Cache decrypted values in a session/Redis if frequently accessed.

Debugging

  • Verify Encryption: Compare plaintext vs. encrypted values:

    $encrypted = $this->bridge->encrypt('test');
    $decrypted = $this->bridge->decrypt($encrypted);
    assert($decrypted === 'test');
    
  • Check Annotations: Ensure @Encrypted() is correctly placed (no typos, valid Doctrine property).

  • Logs: Enable Doctrine logging to debug lifecycle events:

    doctrine:
        orm:
            logging: true
    

Extension Points

  1. Custom Encryptor: Implement EncryptorInterface for non-AES methods (e.g., RSA):

    class RSAEncryptor implements EncryptorInterface {
        public function encrypt($data) { /* ... */ }
        public function decrypt($data) { /* ... */ }
    }
    
  2. Dynamic Suffixes: Override the suffix per entity/field:

    /**
     * @Encrypted(suffix="custom_suffix")
     */
    private $field;
    
  3. Exclude Fields: Use a custom listener to skip encryption for specific fields:

    $em->getEventManager()->addEventListener(
        Doctrine\ORM\Events::prePersist,
        function ($event) {
            $entity = $event->getObject();
            if (isset($entity->skipEncryption)) {
                $event->setNewObject($entity); // Bypass encryption
            }
        }
    );
    
  4. Query Filtering: Use DQL functions to query encrypted fields (requires custom DQL functions):

    $qb->andWhere('FUNCTION("decrypt", u.ssn) = :ssn')
       ->setParameter('ssn', '123-45-6789');
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity