Installation
composer require cleverage/encryption-bundle
Enable the bundle in config/bundles.php:
return [
// ...
Clevage\EncryptionBundle\ClevageEncryptionBundle::class => ['all' => true],
];
Configure the Bundle
Add encryption settings to config/packages/cleverage_encryption.yaml:
cleverage_encryption:
cipher: AES-256-CBC
cipher_key: '%env(ENCRYPTION_KEY)%' # Generate a secure key (e.g., 32-byte hex string)
cipher_iv: '%env(ENCRYPTION_IV)%' # Generate a secure IV (e.g., 16-byte hex string)
First Use Case: Encrypting a Field
Annotate a Doctrine entity field with encrypt_string or encrypt_text:
use Doctrine\ORM\Mapping as ORM;
class User {
/**
* @ORM\Column(type="encrypt_string")
*/
private string $creditCardNumber;
/**
* @ORM\Column(type="encrypt_text")
*/
private string $personalNotes;
}
Run migrations (php bin/console doctrine:migrations:diff and php bin/console doctrine:migrations:migrate).
Encrypting Data The bundle handles encryption/decryption transparently. Just set/get properties as usual:
$user = new User();
$user->setCreditCardNumber('4111111111111111'); // Automatically encrypted on flush
$entityManager->persist($user);
$entityManager->flush();
Querying Encrypted Fields
Use ExpressionBuilder for comparisons:
$qb = $entityManager->createQueryBuilder();
$expr = $qb->expr();
$qb->andWhere($expr->eq('u.creditCardNumber', ':card'))
->setParameter('card', '4111111111111111');
File Encryption
For encrypted file storage (e.g., encrypt_binary), use the File type with a custom FileLoader:
/**
* @ORM\Column(type="encrypt_binary")
*/
private $sensitiveFile;
Multi-Tenancy (Organization-Level Encryption)
Extend the bundle to support organization-specific keys by overriding the CipherKeyProvider:
cleverage_encryption:
cipher_key_provider: app.custom_cipher_key_provider
@ApiProperty with serializedName to expose decrypted data in responses.prePersist/preUpdate to log encryption events or validate data before encryption.Session Dependency The cipher key is decrypted and stored in the session at login. If sessions are disabled or invalidated, decryption fails.
Key Rotation Changing the encryption key breaks existing encrypted data. Plan for key rotation during migrations.
Performance Overhead Encryption/decryption adds ~10-20ms per field. Avoid encrypting frequently queried fields.
encrypt_string for small fields (e.g., credit cards) and encrypt_text for large data.Doctrine DQL Limitations
Encrypted fields cannot be used in ORDER BY, GROUP BY, or complex aggregations.
$this->get('session')->get('cleverage_encryption.cipher_key');
monolog:
handlers:
encryption:
type: stream
path: "%kernel.logs_dir%/encryption.log"
level: debug
Custom Cipher Providers
Implement Clevage\EncryptionBundle\Provider\CipherKeyProviderInterface for dynamic keys:
class OrganizationCipherKeyProvider implements CipherKeyProviderInterface {
public function getCipherKey(): string {
return $this->getOrganizationKey($_SESSION['org_id']);
}
}
Custom Encryption Types
Extend the bundle to support new types (e.g., encrypt_json):
class JsonEncryptionType extends EncryptionType {
public function convertToDatabaseValue($value, AbstractPlatform $platform) {
return parent::convertToDatabaseValue(json_encode($value), $platform);
}
}
Key Management Replace the default key storage with a secrets manager (e.g., AWS KMS):
cleverage_encryption:
cipher_key_provider: app.aws_kms_key_provider
ENCRYPTION_KEY and ENCRYPTION_IV are 32/16-byte hex strings, respectively.php bin/console doctrine:cache:clear-metadata
How can I help you explore Laravel packages today?