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

Encrypted Fields Bundle Laravel Package

dwgebler/encrypted-fields-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Install the Package Add the Flex recipe endpoint to composer.json (optional but recommended):

    "extra": {
        "symfony": {
            "endpoint": ["https://api.github.com/repos/dwgebler/flex-recipes/contents/index.json"]
        }
    }
    

    Install via Composer:

    composer require dwgebler/encrypted-fields-bundle
    
  2. Generate Master Key Create a secure master key file (32-byte hex for AES-256-GCM):

    php -r "file_put_contents('master.key', bin2hex(random_bytes(32)));"
    

    Store the path in .env:

    ENCRYPTED_FIELDS_KEY=file:///path/to/master.key
    
  3. Configure the Bundle Add to config/packages/gebler_encrypted_fields.yaml:

    encrypted_fields:
        master_key: '%env(trim:file:ENCRYPTED_FIELDS_KEY)%'
        cipher: 'aes-256-gcm'
    
  4. Run Migrations Generate and execute the encryption_key table migration:

    php bin/console make:migration
    php bin/console doctrine:migrations:migrate
    
  5. Annotate an Entity Add the #[EncryptedField] attribute to a sensitive field in a Doctrine entity:

    use Gebler\EncryptedFieldsBundle\Attribute\EncryptedField;
    
    #[ORM\Entity]
    class User {
        #[EncryptedField]
        private string $ssn;
    
        #[EncryptedField(elements: ['credit_card'])]
        private array $paymentDetails;
    }
    
  6. Test Encryption Persist and retrieve an entity to verify automatic encryption/decryption:

    $user = new User();
    $user->ssn = '123-45-6789';
    $entityManager->persist($user);
    $entityManager->flush();
    
    $fetchedUser = $entityManager->find(User::class, $user->getId());
    // $fetchedUser->ssn is automatically decrypted
    

Implementation Patterns

Core Workflows

1. Field-Level Encryption

  • Pattern: Use #[EncryptedField] on Doctrine entity properties.
  • Example:
    #[EncryptedField]
    private string $apiKey;
    
    #[EncryptedField(elements: ['token'])]
    private array $authTokens;
    
  • Workflow:
    • On persist() or flush(), the bundle encrypts the field with a per-record key.
    • On find() or getReference(), it decrypts the field automatically.

2. Master Key vs. Per-Record Keys

  • Use useMasterKey: true for fields requiring the master key (e.g., audit logs):
    #[EncryptedField(useMasterKey: true)]
    private string $adminNotes;
    
  • Default Behavior: Per-record keys (stored in encryption_key table) encrypted with the master key.

3. Array Element Encryption

  • Pattern: Encrypt specific nested elements in arrays:
    #[EncryptedField(elements: ['password', 'token'])]
    private array $userCredentials;
    
  • Workflow:
    • Only specified keys (password, token) are encrypted; others remain plaintext.

4. Key Rotation

  • Pattern: Rotate the master key without decrypting all data:

    php bin/console gebler:encryption:rotate-key --generate-new-key
    
  • Workflow:

    1. Generate a new master key.
    2. The command decrypts all per-record keys (using the old master key) and re-encrypts them with the new master key.
    3. Outputs the new key to the console (store securely).
  • Legacy Data Handling:

    php bin/console gebler:encryption:rotate-key --database-key-file=/path/to/old.key --generate-new-key
    

5. Custom Key Management

  • Pattern: Override key generation for specific fields:
    #[EncryptedField(key: 'custom_key_for_this_field')]
    private string $legacyData;
    
  • Use Case: Integrate with existing key management systems (e.g., KMS).

Integration Tips

Symfony-Specific

  1. Dependency Injection:

    • Access the encryption service via:
      $this->container->get('gebler_encrypted_fields.encrypter');
      
    • Or autowire:
      use Gebler\EncryptedFieldsBundle\Encrypter\EncrypterInterface;
      
      public function __construct(private EncrypterInterface $encrypter) {}
      
  2. Event Listeners:

    • Extend functionality by subscribing to Doctrine events:
      use Doctrine\ORM\Events;
      use Gebler\EncryptedFieldsBundle\EventListener\EncryptedFieldListener;
      
      // In services.yaml
      Doctrine\ORM\EntityManager:
          tags: ['doctrine.event_listener']
          calls:
              - [addEventListener, [Events::prePersist, '@gebler_encrypted_fields.listener']]
      
  3. Console Commands:

    • Extend the rotate-key command for custom logic:
      use Gebler\EncryptedFieldsBundle\Command\RotateKeyCommand;
      // Override in a custom command class.
      

Laravel Adaptations

  1. Service Provider:

    • Register the bundle in AppServiceProvider:
      public function register()
      {
          $this->app->register(\Gebler\EncryptedFieldsBundle\EncryptedFieldsBundle::class);
      }
      
  2. Configuration:

    • Publish the config and bind the master key:
      $this->app->bind('gebler_encrypted_fields.master_key', function () {
          return env('ENCRYPTED_FIELDS_KEY');
      });
      
  3. Artisan Commands:

    • Override Symfony commands with Laravel’s Artisan:
      Artisan::command('gebler:encryption:rotate-key', function () {
          // Custom logic or proxy to Symfony command.
      });
      

Performance Optimization

  1. Caching Decrypted Values:

    • Cache decrypted fields in memory (e.g., Symfony Cache or Laravel Cache):
      $cache = $this->container->get('cache.app');
      $cachedValue = $cache->get("user_{$user->id}_ssn", function () use ($user) {
          return $user->ssn; // Automatically decrypted
      });
      
  2. Batch Processing:

    • For bulk operations, decrypt/encrypt outside the ORM:
      $encrypter = $this->container->get('gebler_encrypted_fields.encrypter');
      $plaintext = $encrypter->decrypt($encryptedData);
      
  3. Indexing:

    • Avoid encrypting fields used in WHERE clauses (performance impact). Use computed columns or triggers if needed.

Gotchas and Tips

Pitfalls

  1. OpenSSL Requirement:

    • Error: Class 'OpenSSL' not found.
    • Fix: Ensure the OpenSSL PHP extension is installed:
      sudo apt-get install php-openssl  # Debian/Ubuntu
      sudo dnf install php-openssl      # RHEL/CentOS
      
    • Verification: Run php -m | grep openssl.
  2. Master Key Exposure:

    • Risk: Storing the master key in version control (e.g., config/packages/gebler_encrypted_fields.yaml).
    • Fix: Always use %env() or a secrets manager:
      encrypted_fields:
          master_key: '%env(ENCRYPTED_FIELDS_KEY)%'
      
  3. Proxy Objects:

    • Issue: Doctrine proxy objects may fail to decrypt fields if the real class isn’t checked.
    • Fix: Upgrade to v1.2.1+ (includes a fix for this).
  4. Key Rotation Downtime:

    • Risk: The rotate-key command locks the encryption_key table during re-encryption.
    • Mitigation: Run during low-traffic periods or use a read replica.
  5. Large Binary Fields:

    • Issue: Encrypting large BLOB/TEXT fields may hit memory limits.
    • Workaround: Use chunked encryption or database-level encryption (e.g., PostgreSQL pgcrypto).
  6. Multi-Environment Keys:

    • Problem: Using the same master key across dev/staging/prod risks key leakage.
    • Solution: Generate environment-specific keys and use --database-key-file during migrations.
  7. Schema Conflicts:

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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
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
christhompsontldr/laravel-inky