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

Data Protection Bundle Laravel Package

ekino/data-protection-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require ekino/data-protection-bundle
    

    Register the bundle in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 2/3).

  2. Basic Configuration (config/packages/ekino_data_protection.yaml):

    ekino_data_protection:
        encryption_key: '%env(ENCRYPTION_KEY)%'  # 32-byte key for AES-256
        default_algorithm: 'AES-256-CBC'        # Default encryption algorithm
    

    Ensure ENCRYPTION_KEY is set in .env (e.g., ENCRYPTION_KEY=your_32_byte_base64_encoded_key).

  3. First Use Case: Encrypt/decrypt a string via a service:

    use Ekino\DataProtectionBundle\Service\DataProtector;
    
    class MyService {
        public function __construct(private DataProtector $protector) {}
    
        public function protectData(string $data): string {
            return $this->protector->encrypt($data);
        }
    
        public function unprotectData(string $encryptedData): string {
            return $this->protector->decrypt($encryptedData);
        }
    }
    

Implementation Patterns

Core Workflows

  1. Field-Level Encryption: Use the bundle’s Doctrine listeners to auto-encrypt/decrypt entity fields:

    ekino_data_protection:
        entities:
            App\Entity\SensitiveData:
                fields:
                    - creditCardNumber
                    - ssn
    

    The bundle handles encryption/decryption transparently during prePersist/preUpdate.

  2. API Payload Protection: Protect sensitive data in API responses using serializer groups:

    #[Groups(['api'])]
    #[Ekino\DataProtectionBundle\Annotation\Protected]
    private string $passwordHash;
    

    Configure the serializer to use the protected group in config/packages/serializer.yaml.

  3. Custom Encryption Logic: Extend the DataProtector service or create a custom protector:

    class CustomProtector extends DataProtector {
        public function encryptWithMetadata(string $data, array $metadata): string {
            // Custom logic (e.g., add timestamps, IVs)
            return parent::encrypt($data);
        }
    }
    

    Bind it in services.yaml:

    services:
        App\Service\CustomProtector:
            arguments:
                $encryptionKey: '%env(ENCRYPTION_KEY)%'
                $algorithm: 'AES-256-CBC'
    
  4. Bulk Operations: Use the DataProtector for batch processing (e.g., CSV imports/exports):

    $protector = $this->container->get(DataProtector::class);
    $encryptedData = array_map([$protector, 'encrypt'], $plainDataArray);
    

Integration Tips

  • Doctrine: Works seamlessly with Doctrine entities. For complex types (e.g., arrays), use @Assert\Type or custom accessors.
  • Symfony Forms: Bind encrypted fields to form types, but handle validation carefully (compare encrypted values).
  • Caching: Cache encrypted data only if the cache key is also encrypted (use hash() on encrypted strings).
  • Testing: Mock DataProtector in unit tests:
    $this->mockBuilder(DataProtector::class)
         ->disableOriginalConstructor()
         ->getMock()
         ->method('encrypt')
         ->willReturn('encrypted_placeholder');
    

Gotchas and Tips

Pitfalls

  1. Key Management:

    • Never hardcode keys in config. Use .env or a secrets manager (e.g., AWS Secrets Manager).
    • Rotate keys carefully: Re-encrypt data when keys change (use a migration or CLI script).
    • Key length: AES-256 requires a 32-byte (256-bit) key. Generate it with:
      openssl rand -base64 32
      
  2. Algorithm Quirks:

    • CBC mode requires a unique Initialization Vector (IV) per encryption. The bundle auto-generates IVs but prepends them to ciphertext (increases payload size by 16 bytes).
    • GCM mode (if supported) is preferred for authenticity but may not be enabled by default. Configure in ekino_data_protection.yaml:
      default_algorithm: 'AES-256-GCM'
      
  3. Doctrine Caveats:

    • Field length: Encrypted data is longer than plaintext. Adjust column length in DB migrations (e.g., TEXT instead of VARCHAR(255)).
    • Lazy loading: Encrypted fields may cause N+1 queries if not fetched eagerly. Use fetch="EAGER" or DQL JOIN:
      $query->addSelect('PARTIAL s.0->creditCardNumber'); // Partial load
      
  4. Serialization Issues:

    • JSON encoding: Encrypted data may contain non-JSON-safe characters (e.g., + in Base64). Use json_encode($data, JSON_UNESCAPED_UNICODE).
    • Symfony Serializer: If using @Protected, ensure the serializer is configured to handle encrypted data in both directions.
  5. Performance:

    • Avoid encrypting in loops: Batch operations (e.g., bulk inserts) can be slow. Consider async processing for large datasets.
    • Cache encryption keys: The bundle caches keys in memory by default. Disable if using a shared cache (e.g., Redis) across multiple apps.

Debugging Tips

  1. Validation Errors:

    • If decryption fails, check:
      • The key is correct (compare with .env).
      • The algorithm matches what was used for encryption.
      • The data is not corrupted (e.g., truncated during DB storage).
    • Enable debug mode to log errors:
      ekino_data_protection:
          debug: true
      
  2. Doctrine Errors:

    • Column not found: Ensure the field name in ekino_data_protection.yaml matches the entity property.
    • Type mismatch: Use @ORM\Column(type="text") for encrypted fields.
  3. Logging:

    • Enable monolog for the bundle:
      monolog:
          handlers:
              data_protection:
                  type: stream
                  path: "%kernel.logs_dir%/data_protection.log"
                  level: debug
                  channels: ["data_protection"]
      
    • Configure the bundle to use the channel:
      ekino_data_protection:
          logger_channel: "data_protection"
      

Extension Points

  1. Custom Encryption Algorithms: Implement Ekino\DataProtectionBundle\Algorithm\AlgorithmInterface:

    class MyAlgorithm implements AlgorithmInterface {
        public function encrypt(string $data, string $key): string { /* ... */ }
        public function decrypt(string $data, string $key): string { /* ... */ }
    }
    

    Register it in services.yaml:

    services:
        App\Algorithm\MyAlgorithm:
            tags: ['ekino_data_protection.algorithm']
    
  2. Pre/Post-Encryption Hooks: Use Symfony’s event system to intercept encryption/decryption:

    // config/services.yaml
    Ekino\DataProtectionBundle\EventListener\DataProtectionListener:
        tags:
            - { name: kernel.event_listener, event: ekino.data_protection.encrypt, method: onEncrypt }
            - { name: kernel.event_listener, event: ekino.data_protection.decrypt, method: onDecrypt }
    
  3. Custom Metadata: Attach metadata to encrypted data (e.g., expiration timestamps):

    $metadata = ['expires_at' => time() + 3600];
    $protectedData = $protector->encryptWithMetadata($data, $metadata);
    

    Retrieve metadata during decryption:

    $decrypted = $protector->decryptWithMetadata($protectedData);
    $metadata = $decrypted['metadata'];
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui