{"id":31939296,"url":"https://github.com/paragonie/doctrine-ciphersweet","last_synced_at":"2025-10-14T08:25:04.871Z","repository":{"id":317565481,"uuid":"1067950932","full_name":"paragonie/doctrine-ciphersweet","owner":"paragonie","description":"Use searchable encryption with Doctrine ORM, powered by CipherSweet. Useful for Symfony apps.","archived":false,"fork":false,"pushed_at":"2025-10-01T16:54:43.000Z","size":11,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-01T18:31:49.574Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paragonie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-01T16:16:17.000Z","updated_at":"2025-10-01T16:54:46.000Z","dependencies_parsed_at":"2025-10-01T18:31:53.935Z","dependency_job_id":null,"html_url":"https://github.com/paragonie/doctrine-ciphersweet","commit_stats":null,"previous_names":["paragonie/doctrine-ciphersweet"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/paragonie/doctrine-ciphersweet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paragonie%2Fdoctrine-ciphersweet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paragonie%2Fdoctrine-ciphersweet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paragonie%2Fdoctrine-ciphersweet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paragonie%2Fdoctrine-ciphersweet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paragonie","download_url":"https://codeload.github.com/paragonie/doctrine-ciphersweet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paragonie%2Fdoctrine-ciphersweet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018312,"owners_count":26086342,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-14T08:25:01.195Z","updated_at":"2025-10-14T08:25:04.866Z","avatar_url":"https://github.com/paragonie.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Doctrine-CipherSweet Adapter\n\n[![Build Status](https://github.com/paragonie/doctrine-ciphersweet/actions/workflows/ci.yml/badge.svg)](https://github.com/paragonie/doctrine-ciphersweet/actions)\n[![Example App](https://github.com/paragonie/doctrine-ciphersweet/actions/workflows/example-app.yml/badge.svg)](https://github.com/paragonie/doctrine-ciphersweet/tree/main/docs/example-app)\n[![Static Analysis](https://github.com/paragonie/doctrine-ciphersweet/actions/workflows/psalm.yml/badge.svg)](https://github.com/paragonie/doctrine-ciphersweet/actions)\n[![Latest Stable Version](https://poser.pugx.org/paragonie/doctrine-ciphersweet/v/stable)](https://packagist.org/packages/paragonie/doctrine-cipherrsweet)\n[![Latest Unstable Version](https://poser.pugx.org/paragonie/doctrine-ciphersweet/v/unstable)](https://packagist.org/packages/paragonie/doctrine-cipherrsweet)\n[![License](https://poser.pugx.org/paragonie/doctrine-ciphersweet/license)](https://packagist.org/packages/paragonie/doctrine-ciphersweet)\n[![Downloads](https://img.shields.io/packagist/dt/paragonie/doctrine-ciphersweet.svg)](https://packagist.org/packages/paragonie/doctrine-ciphersweet)\n\nUse searchable encryption with [Doctrine ORM](https://github.com/doctrine/orm), powered by \n[CipherSweet](https://ciphersweet.paragonie.com/).\n\n## Installation\n\n```bash\ncomposer require paragonie/doctrine-ciphersweet\n```\n\n## Usage\n\nFirst, you need to create a `ParagonIE\\CipherSweet\\CipherSweet` object. Please refer to \n[the CipherSweet docs](https://ciphersweet.paragonie.com/php/setup).\n\n```php\nuse ParagonIE\\CipherSweet\\CipherSweet;\nuse ParagonIE\\CipherSweet\\KeyProvider\\StringProvider;\n\n$keyProvider = new StringProvider(random_bytes(32));\n$engine = new CipherSweet($keyProvider);\n```\n\nNext, create an `EncryptedFieldSubscriber` and register it with your `EntityManager`.\n\n```php\nuse ParagonIE\\DoctrineCipher\\Event\\EncryptedFieldSubscriber;\n\n$subscriber = new EncryptedFieldSubscriber($engine);\n$entityManager-\u003egetEventManager()-\u003eaddEventSubscriber($subscriber);\n```\n\nNow you can use the `#[Encrypted]` attribute on your entity properties.\n\n```php\nuse Doctrine\\ORM\\Mapping as ORM;\nuse ParagonIE\\DoctrineCipher\\Attribute\\Encrypted;\n\n#[ORM\\Entity]\nclass Message\n{\n    #[ORM\\Id]\n    #[ORM\\Column(type: 'integer')]\n    #[ORM\\GeneratedValue]\n    private int $id;\n\n    #[ORM\\Column(type: 'text')]\n    #[Encrypted]\n    private string $text;\n    \n    #[ORM\\Column(type: 'string', length: 255, nullable: true)]\n    private ?string $textBlindIndexInsensitive;\n\n    public function __construct(string $text)\n    {\n        $this-\u003etext = $text;\n    }\n\n    // ... getters and setters\n}\n```\n\nWhen you persist an entity, the `EncryptedFieldSubscriber` will automatically encrypt the properties that have the\n`#[Encrypted]` attribute.\n\n```php\n$message = new Message('This is a secret message.');\n$entityManager-\u003epersist($message);\n$entityManager-\u003eflush();\n```\n\nWhen you retrieve an entity, the encrypted properties will be automatically decrypted.\n\n```php\n$message = $entityManager-\u003efind(Message::class, 1);\necho $message-\u003egetText(); // \"This is a secret message.\"\n```\n\n### Blind Indexes\n\nYou can also use blind indexes for searchable encryption. To do this, add a `blindIndexes` argument to the \n`#[Encrypted]` attribute.\n\n```php\nuse Doctrine\\ORM\\Mapping as ORM;\nuse ParagonIE\\DoctrineCipher\\Attribute\\Encrypted;\n\n#[ORM\\Entity]\nclass Message\n{\n    #[ORM\\Id]\n    #[ORM\\Column(type: 'integer')]\n    #[ORM\\GeneratedValue]\n    private int $id;\n\n    #[ORM\\Column(type: 'text')]\n    #[Encrypted(blindIndexes: ['insensitive' =\u003e 'case-insensitive'])]\n    private string $text;\n\n    #[ORM\\Column(type: 'string', length: 255, nullable: true)]\n    private ?string $textBlindIndexInsensitive;\n\n    public function __construct(string $text)\n    {\n        $this-\u003etext = $text;\n    }\n\n    // ... getters and setters\n}\n```\n\nYou also need to register a transformer for the blind index.\n\n```php\nuse ParagonIE\\CipherSweet\\Transformation\\Lowercase;\n\n$subscriber-\u003eaddTransformer('case-insensitive', Lowercase::class);\n```\n\nNow you can query the blind index.\n\nTo do so, you must first calculate the blind index for your search term.\n\n```php\nuse ParagonIE\\CipherSweet\\BlindIndex;\nuse ParagonIE\\CipherSweet\\EncryptedField;\n\n// First, you need to get the blind index for your search term.\n// Note: The EncryptedField must be configured exactly as it is for the entity.\n$encryptedField = new EncryptedField($engine, 'messages', 'text');\n$encryptedField-\u003eaddBlindIndex(new BlindIndex('insensitive', [new Lowercase()]));\n\n$searchTerm = 'this is a secret message.';\n$blindIndex = $encryptedField-\u003egetBlindIndex($searchTerm, 'insensitive');\n\n// Now you can use this blind index to query the database.\n$repository = $entityManager-\u003egetRepository(Message::class);\n$message = $repository-\u003efindOneBy(['textBlindIndexInsensitive' =\u003e $blindIndex]);\n```\n\n## Support Contracts\n\nIf your company uses this library in their products or services, you may be\ninterested in [purchasing a support contract from Paragon Initiative Enterprises](https://paragonie.com/enterprise).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparagonie%2Fdoctrine-ciphersweet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparagonie%2Fdoctrine-ciphersweet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparagonie%2Fdoctrine-ciphersweet/lists"}