paragonie / doctrine-ciphersweet
Requires
- php: ^8.2
- doctrine/orm: ^3
- paragonie/ciphersweet: ^4
Requires (Dev)
- phpunit/phpunit: ^11
- symfony/cache: ^7.3
This package is auto-updated.
Last update: 2025-10-02 08:22:14 UTC
README
Use searchable encryption with Doctrine ORM, powered by CipherSweet.
Installation
composer require paragonie/doctrine-ciphersweet
Usage
First, you need to create a ParagonIE\CipherSweet\CipherSweet
object. Please refer to
the CipherSweet docs.
use ParagonIE\CipherSweet\CipherSweet; use ParagonIE\CipherSweet\KeyProvider\StringProvider; $keyProvider = new StringProvider(random_bytes(32)); $engine = new CipherSweet($keyProvider);
Next, create an EncryptedFieldSubscriber
and register it with your EntityManager
.
use ParagonIE\DoctrineCipher\Event\EncryptedFieldSubscriber; $subscriber = new EncryptedFieldSubscriber($engine); $entityManager->getEventManager()->addEventSubscriber($subscriber);
Now you can use the #[Encrypted]
attribute on your entity properties.
use Doctrine\ORM\Mapping as ORM; use ParagonIE\DoctrineCipher\Attribute\Encrypted; #[ORM\Entity] class Message { #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] private int $id; #[ORM\Column(type: 'text')] #[Encrypted] private string $text; #[ORM\Column(type: 'string', length: 255, nullable: true)] private ?string $textBlindIndexInsensitive; public function __construct(string $text) { $this->text = $text; } // ... getters and setters }
When you persist an entity, the EncryptedFieldSubscriber
will automatically encrypt the properties that have the
#[Encrypted]
attribute.
$message = new Message('This is a secret message.'); $entityManager->persist($message); $entityManager->flush();
When you retrieve an entity, the encrypted properties will be automatically decrypted.
$message = $entityManager->find(Message::class, 1); echo $message->getText(); // "This is a secret message."
Blind Indexes
You can also use blind indexes for searchable encryption. To do this, add a blindIndexes
argument to the
#[Encrypted]
attribute.
use Doctrine\ORM\Mapping as ORM; use ParagonIE\DoctrineCipher\Attribute\Encrypted; #[ORM\Entity] class Message { #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] private int $id; #[ORM\Column(type: 'text')] #[Encrypted(blindIndexes: ['insensitive' => 'case-insensitive'])] private string $text; #[ORM\Column(type: 'string', length: 255, nullable: true)] private ?string $textBlindIndexInsensitive; public function __construct(string $text) { $this->text = $text; } // ... getters and setters }
You also need to register a transformer for the blind index.
use ParagonIE\CipherSweet\Transformation\Lowercase; $subscriber->addTransformer('case-insensitive', Lowercase::class);
Now you can query the blind index.
To do so, you must first calculate the blind index for your search term.
use ParagonIE\CipherSweet\BlindIndex; use ParagonIE\CipherSweet\EncryptedField; // First, you need to get the blind index for your search term. // Note: The EncryptedField must be configured exactly as it is for the entity. $encryptedField = new EncryptedField($engine, 'messages', 'text'); $encryptedField->addBlindIndex(new BlindIndex('insensitive', [new Lowercase()])); $searchTerm = 'this is a secret message.'; $blindIndex = $encryptedField->getBlindIndex($searchTerm, 'insensitive'); // Now you can use this blind index to query the database. $repository = $entityManager->getRepository(Message::class); $message = $repository->findOneBy(['textBlindIndexInsensitive' => $blindIndex]);
Support Contracts
If your company uses this library in their products or services, you may be interested in purchasing a support contract from Paragon Initiative Enterprises.