> For the complete MongoDB documentation index, see www.mongodb.com/docs/llms.txt

# In-Use Encryption

## Dependencies

To get started using in-use encryption in your project, the [extension](https://php.net/mongodb) will need to be compiled with [libmongocrypt](https://github.com/mongodb/libmongocrypt) (enabled by default).

Additionally, either `crypt_shared` or `mongocryptd` are required in order to use *automatic* client-side encryption. Neither is required for *explicit* encryption.

### `crypt_shared`

The [Automatic Encryption Shared Library](https://www.mongodb.com/docs/manual/core/queryable-encryption/reference/shared-library/) (`crypt_shared`) provides the same functionality as `mongocryptd`, but does not require you to spawn another process to perform automatic encryption.

By default, the extension attempts to load `crypt_shared` from the system path(s) and uses it automatically if found. To load `crypt_shared` from another location, use the `cryptSharedLibPath` auto encryption [driver option](https://php.net/manual/en/mongodb-driver-manager.construct.php#mongodb-driver-manager.construct-driveroptions) when constructing a client. If the extension cannot load `crypt_shared` it will attempt to fallback to using `mongocryptd` by default. The `cryptSharedLibRequired` option may be used to always require `crypt_shared` and fail if it cannot be loaded.

For detailed installation instructions see the MongoDB documentation for the [Automatic Encryption Shared Library.](https://www.mongodb.com/docs/manual/core/queryable-encryption/reference/shared-library/)

### `mongocryptd`

The `mongocryptd` binary is an alternative requirement for automatic client-side encryption and is included as a component in the [MongoDB Enterprise Server package](https://www.mongodb.com/docs/manual/administration/install-enterprise/). For detailed installation instructions see the [MongoDB documentation on mongocryptd.](https://www.mongodb.com/docs/manual/core/csfle/reference/mongocryptd/)

`mongocryptd` performs the following:

- Parses the automatic encryption rules specified in the client configuration. If the `schemaMap` auto encryption driver option contains invalid syntax, `mongocryptd` returns an error.

- Uses the specified automatic encryption rules to mark fields in read and write operations for encryption.

- Rejects read/write operations that may return unexpected or incorrect results when applied to an encrypted field. For supported and unsupported operations, see [Supported Operations for Automatic Encryption.](https://www.mongodb.com/docs/manual/core/csfle/reference/supported-operations/)

A client configured with auto encryption will automatically spawn the `mongocryptd` process from the application's `PATH`. Applications can control the spawning behavior via various auto encryption [driver options.](https://php.net/manual/en/mongodb-driver-manager.construct.php#mongodb-driver-manager.construct-driveroptions)

`mongocryptd` is only responsible for supporting automatic client-side encryption and does not itself perform any encryption or decryption.

## Managing Encryption Keys

**See also:**

### Creating an Encryption Key

**Note:**

The following examples use a local master key. While this is suitable for development, a production application should use a supported cloud provider (e.g. AWS KMS). The master key is used to encrypt locally stored data keys and thus it is very important that you keep this key secure.

To create an encryption key, create a [MongoDB\Driver\ClientEncryption](https://php.net/class.mongodb-driver-clientencryption) instance with encryption options and use the [createDataKey()](https://php.net/manual/en/mongodb-driver-clientencryption.createdatakey.php) method. The method will return the key ID which can be used to reference the key later. You can also pass multiple [alternate names](https://www.mongodb.com/docs/php-library/current/tutorial/encryption.md#std-label-alt_name) for this key and reference the key by these names instead of the key ID.

Creating a new data encryption key would typically be done on initial deployment, but depending on your use case you may want to use more than one encryption key (e.g. user-specific encryption keys) or create them dynamically.

```php
<?php

use MongoDB\BSON\Binary;
use MongoDB\Client;
use MongoDB\Driver\ClientEncryption;

require __DIR__ . '/../../../vendor/autoload.php';

$uri = getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/';

// Generate a secure local key to use for this script
$localKey = new Binary(random_bytes(96));

// Create a client with no encryption options
$client = new Client($uri);

/* Prepare the database for this script. Drop the key vault collection and
 * ensure it has a unique index for keyAltNames. This would typically be done
 * during application deployment. */
$client->getCollection('encryption', '__keyVault')->drop();
$client->getCollection('encryption', '__keyVault')->createIndex(['keyAltNames' => 1], [
    'unique' => true,
    'partialFilterExpression' => ['keyAltNames' => ['$exists' => true]],
]);

// Create a ClientEncryption object to manage data encryption keys
$clientEncryption = $client->createClientEncryption([
    'keyVaultNamespace' => 'encryption.__keyVault',
    'kmsProviders' => [
        'local' => ['key' => $localKey],
    ],
]);

/* Create a data encryption key. To store the key ID for later use, you can use
 * serialize(), var_export(), etc. */
$keyId = $clientEncryption->createDataKey('local');

print_r($keyId);

// Encrypt a value using the key that was just created
$encryptedValue = $clientEncryption->encrypt('mySecret', [
    'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
    'keyId' => $keyId,
]);

print_r($encryptedValue);

```

### Referencing Encryption Keys by an Alternative Name

To reference keys in your application, you can use the `keyAltName` attribute specified when creating the key. The following example creates an encryption key with an alternative name, which could be done when deploying the application. The script then encrypts data by referencing the key by its alternative name using the `keyAltName` option instead of `keyId`.

**Note:**

Prior to adding a new key alternate name, you must create a partial, unique index on the `keyAltNames` field. Client-Side Field Level Encryption depends on server-enforced uniqueness of key alternate names.

```php
<?php

use MongoDB\BSON\Binary;
use MongoDB\Client;
use MongoDB\Driver\ClientEncryption;
use MongoDB\Driver\Exception\ServerException;

require __DIR__ . '/../../../vendor/autoload.php';

$uri = getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/';

// Generate a secure local key to use for this script
$localKey = new Binary(random_bytes(96));

// Create a client with no encryption options
$client = new Client($uri);

/* Prepare the database for this script. Drop the key vault collection and
 * ensure it has a unique index for keyAltNames. This would typically be done
 * during application deployment. */
$client->getCollection('encryption', '__keyVault')->drop();
$client->getCollection('encryption', '__keyVault')->createIndex(['keyAltNames' => 1], [
    'unique' => true,
    'partialFilterExpression' => ['keyAltNames' => ['$exists' => true]],
]);

// Create a ClientEncryption object to manage data encryption keys
$clientEncryption = $client->createClientEncryption([
    'keyVaultNamespace' => 'encryption.__keyVault',
    'kmsProviders' => [
        'local' => ['key' => $localKey],
    ],
]);

// Create a data encryption key with an alternate name
$clientEncryption->createDataKey('local', ['keyAltNames' => ['myDataKey']]);

/* Attempt to create a second key with the same name to demonstrate that the
 * unique index is enforced. */
try {
    $clientEncryption->createDataKey('local', ['keyAltNames' => ['myDataKey']]);
} catch (ServerException $e) {
    printf("Error creating key: %s\n", $e->getMessage());
}

// Encrypt a value, using the "keyAltName" option instead of "keyId"
$encryptedValue = $clientEncryption->encrypt('mySecret', [
    'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
    'keyAltName' => 'myDataKey',
]);

print_r($encryptedValue);

```

## Client-Side Field Level Encryption

[Client-Side Field Level Encryption](https://www.mongodb.com/docs/manual/core/csfle/) allows an application to encrypt specific data fields in addition to pre-existing MongoDB encryption features such as [Encryption at Rest](https://www.mongodb.com/docs/manual/core/security-encryption-at-rest/) and [TLS/SSL (Transport Encryption).](https://www.mongodb.com/docs/manual/core/security-transport-encryption/)

With field level encryption, applications can encrypt fields in documents prior to transmitting data over the wire to the server. Client-side field level encryption supports workloads where applications must guarantee that unauthorized parties, including server administrators, cannot read the encrypted data.

### Automatic Client-Side Field Level Encryption

**Note:**

To use the automatic client-side field level encryption feature, you must connect to an Enterprise or Atlas cluster.

Automatic client-side field level encryption is enabled by creating a client and specifying the `autoEncryption` [driver option](https://php.net/manual/en/mongodb-driver-manager.construct.php#mongodb-driver-manager.construct-driveroptions). The following examples demonstrate how to setup automatic client-side field level encryption and use a [MongoDB\Driver\ClientEncryption](https://php.net/class.mongodb-driver-clientencryption) object to create a new encryption key.

#### Server-Side Field Level Encryption Enforcement

You can use schema validation to enforce encryption of specific fields in a collection. This schema validation will prevent an application from inserting unencrypted values for any fields marked with the ["encrypt" schema keyword.](https://www.mongodb.com/docs/manual/core/csfle/reference/encryption-schemas/)

The following example sets up a collection with automatic encryption using a `$jsonSchema` validator and [Encryption Schema syntax](https://www.mongodb.com/docs/manual/core/csfle/fundamentals/create-schema/). Data in the `encryptedField` field is automatically encrypted on insertion and decrypted when reading on the client side.

```php
<?php

use MongoDB\BSON\Binary;
use MongoDB\Client;
use MongoDB\Driver\ClientEncryption;
use MongoDB\Driver\Exception\ServerException;

require __DIR__ . '/../../../vendor/autoload.php';

$uri = getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/';

/* Note: this script assumes that the test database is empty and that the key
 * vault collection exists and has a partial, unique index on keyAltNames (as
 * demonstrated in the encryption key management scripts). */

// Generate a secure local key to use for this script
$localKey = new Binary(random_bytes(96));

// Create a client with no encryption options
$client = new Client($uri);

// Create a ClientEncryption object to manage data encryption keys
$clientEncryption = $client->createClientEncryption([
    'keyVaultNamespace' => 'encryption.__keyVault',
    'kmsProviders' => [
        'local' => ['key' => $localKey],
    ],
]);

/* Create a data encryption key. Alternatively, this key ID could be read from a
 * configuration file. */
$keyId = $clientEncryption->createDataKey('local');

// Create another client with automatic encryption enabled
$encryptedClient = new Client($uri, [], [
    'autoEncryption' => [
        'keyVaultNamespace' => 'encryption.__keyVault',
        'kmsProviders' => ['local' => ['key' => $localKey]],
    ],
]);

// Define a JSON schema for the encrypted collection
$schema = [
    'bsonType' => 'object',
    'properties' => [
        'encryptedField' => [
            'encrypt' => [
                'keyId' => [$keyId],
                'bsonType' => 'string',
                'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
            ],
        ],
    ],
];

/* Create a new collection for this script. Configure a server-side schema by
 * explicitly creating the collection with a "validator" option. */
$encryptedClient->getDatabase('test')->createCollection('coll', ['validator' => ['$jsonSchema' => $schema]]);
$encryptedCollection = $encryptedClient->getCollection('test', 'coll');

/* Using the encrypted client, insert and find a document to demonstrate that
 * the encrypted field is automatically encrypted and decrypted. */
$encryptedCollection->insertOne(['_id' => 1, 'encryptedField' => 'mySecret']);

print_r($encryptedCollection->findOne(['_id' => 1]));

/* Using the client configured without encryption, find the same document and
 * observe that the field is not automatically decrypted. */
$unencryptedCollection = $client->getCollection('test', 'coll');

print_r($unencryptedCollection->findOne(['_id' => 1]));

/* Attempt to insert another document with an unencrypted field value to
 * demonstrate that the server-side schema is enforced. */
try {
    $unencryptedCollection->insertOne(['_id' => 2, 'encryptedField' => 'myOtherSecret']);
} catch (ServerException $e) {
    printf("Error inserting document: %s\n", $e->getMessage());
}

```

#### Providing Local Automatic Encryption Rules

The following example uses the `schemaMap` auto encryption driver option to define encrypted fields using a [strict subset of the JSON schema syntax.](https://www.mongodb.com/docs/manual/core/csfle/fundamentals/create-schema/)

Using `schemaMap` in conjunction with a [server-side schema](https://www.mongodb.com/docs/php-library/current/tutorial/encryption.md#std-label-server-side) provides more security than relying entirely on a schema obtained from the server. It protects against a malicious server advertising a false schema, which could trick the client into sending unencrypted data that should be encrypted.

**Note:**

Only [Encryption Schema syntax](https://www.mongodb.com/docs/manual/core/csfle/reference/encryption-schemas/) can be used with the `schemaMap` option. Do not specify document validation keywords in the automatic encryption rules. To define document validation rules, configure [schema validation.](https://www.mongodb.com/docs/manual/core/schema-validation/)

```php
<?php

use MongoDB\BSON\Binary;
use MongoDB\Client;
use MongoDB\Driver\ClientEncryption;
use MongoDB\Driver\Exception\ServerException;

require __DIR__ . '/../../../vendor/autoload.php';

$uri = getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/';

/* Note: this script assumes that the test database is empty and that the key
 * vault collection exists and has a partial, unique index on keyAltNames (as
 * demonstrated in the encryption key management scripts). */

// Generate a secure local key to use for this script
$localKey = new Binary(random_bytes(96));

// Create a client with no encryption options
$client = new Client($uri);

// Create a ClientEncryption object to manage data encryption keys
$clientEncryption = $client->createClientEncryption([
    'keyVaultNamespace' => 'encryption.__keyVault',
    'kmsProviders' => [
        'local' => ['key' => $localKey],
    ],
]);

/* Create a data encryption key. Alternatively, this key ID could be read from a
 * configuration file. */
$keyId = $clientEncryption->createDataKey('local');

/* Define a JSON schema for the encrypted collection. Since this only utilizes
 * encryption schema syntax, it can be used for both the server-side and local
 * schema. */
$schema = [
    'bsonType' => 'object',
    'properties' => [
        'encryptedField' => [
            'encrypt' => [
                'keyId' => [$keyId],
                'bsonType' => 'string',
                'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
            ],
        ],
    ],
];

/* Create another client with automatic encryption enabled. Configure a local
 * schema for the encrypted collection using the "schemaMap" option. */
$encryptedClient = new Client($uri, [], [
    'autoEncryption' => [
        'keyVaultNamespace' => 'encryption.__keyVault',
        'kmsProviders' => ['local' => ['key' => $localKey]],
        'schemaMap' => ['test.coll' => $schema],
    ],
]);

/* Create a new collection for this script. Configure a server-side schema by
 * explicitly creating the collection with a "validator" option.
 *
 * Note: without a server-side schema, another client could potentially insert
 * unencrypted data into the collection. Therefore, a local schema should always
 * be used in conjunction with a server-side schema. */
$encryptedClient->getDatabase('test')->createCollection('coll', ['validator' => ['$jsonSchema' => $schema]]);
$encryptedCollection = $encryptedClient->getCollection('test', 'coll');

/* Using the encrypted client, insert and find a document to demonstrate that
 * the encrypted field is automatically encrypted and decrypted. */
$encryptedCollection->insertOne(['_id' => 1, 'encryptedField' => 'mySecret']);

print_r($encryptedCollection->findOne(['_id' => 1]));

/* Using the client configured without encryption, find the same document and
 * observe that the field is not automatically decrypted. */
$unencryptedCollection = $client->getCollection('test', 'coll');

print_r($unencryptedCollection->findOne(['_id' => 1]));

/* Attempt to insert another document with an unencrypted field value to
 * demonstrate that the server-side schema is enforced. */
try {
    $unencryptedCollection->insertOne(['_id' => 2, 'encryptedField' => 'myOtherSecret']);
} catch (ServerException $e) {
    printf("Error inserting document: %s\n", $e->getMessage());
}

```

### Explicit Encryption

Explicit encryption is a MongoDB community feature and does not use `crypt_shared` or `mongocryptd`. Explicit encryption is provided by the [MongoDB\Driver\ClientEncryption](https://php.net/mongodb-driver-clientencryption) class.

```php
<?php

use MongoDB\BSON\Binary;
use MongoDB\Client;
use MongoDB\Driver\ClientEncryption;

require __DIR__ . '/../../../vendor/autoload.php';

$uri = getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/';

/* Note: this script assumes that the test database is empty and that the key
 * vault collection exists and has a partial, unique index on keyAltNames (as
 * demonstrated in the encryption key management scripts). */

// Generate a secure local key to use for this script
$localKey = new Binary(random_bytes(96));

// Create a client with no encryption options
$client = new Client($uri);

// Create a ClientEncryption object to manage data encryption keys
$clientEncryption = $client->createClientEncryption([
    'keyVaultNamespace' => 'encryption.__keyVault',
    'kmsProviders' => [
        'local' => ['key' => $localKey],
    ],
]);

/* Create a data encryption key. Alternatively, this key ID could be read from a
 * configuration file. */
$keyId = $clientEncryption->createDataKey('local');

// Insert a document with a manually encrypted field
$encryptedValue = $clientEncryption->encrypt('mySecret', [
    'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
    'keyId' => $keyId,
]);

$collection = $client->getCollection('test', 'coll');
$collection->insertOne(['_id' => 1, 'encryptedField' => $encryptedValue]);

/* Using the client configured without encryption, find the document and observe
 * that the field is not automatically decrypted. */

/** @var object{encryptedField: Binary} $document */
$document = $collection->findOne();

print_r($document);

// Manually decrypt the field
printf("Decrypted: %s\n", $clientEncryption->decrypt($document->encryptedField));

```

### Explicit Encryption with Automatic Decryption

Automatic *decryption* is supported for all users. To configure automatic decryption without automatic encryption set the `bypassAutoEncryption` auto encryption [driver option](https://php.net/manual/en/mongodb-driver-manager.construct.php#mongodb-driver-manager.construct-driveroptions) when constructing a client.

```php
<?php

use MongoDB\BSON\Binary;
use MongoDB\Client;
use MongoDB\Driver\ClientEncryption;

require __DIR__ . '/../../../vendor/autoload.php';

$uri = getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/';

/* Note: this script assumes that the test database is empty and that the key
 * vault collection exists and has a partial, unique index on keyAltNames (as
 * demonstrated in the encryption key management scripts). */

// Generate a secure local key to use for this script
$localKey = new Binary(random_bytes(96));

// Create a client with automatic encryption disabled
$client = new Client($uri, [], [
    'autoEncryption' => [
        'keyVaultNamespace' => 'encryption.__keyVault',
        'kmsProviders' => ['local' => ['key' => $localKey]],
        'bypassAutoEncryption' => true,
    ],
]);

// Create a ClientEncryption object to manage data encryption keys
$clientEncryption = $client->createClientEncryption([
    'keyVaultNamespace' => 'encryption.__keyVault',
    'kmsProviders' => [
        'local' => ['key' => $localKey],
    ],
]);

/* Create a data encryption key. Alternatively, this key ID could be read from a
 * configuration file. */
$keyId = $clientEncryption->createDataKey('local');

// Insert a document with a manually encrypted field
$encryptedValue = $clientEncryption->encrypt('mySecret', [
    'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
    'keyId' => $keyId,
]);

$collection = $client->getCollection('test', 'coll');
$collection->insertOne(['_id' => 1, 'encryptedField' => $encryptedValue]);

/* Using the client configured with encryption (but not automatic encryption),
 * find the document and observe that the field is automatically decrypted. */
$document = $collection->findOne();

print_r($document);

```

## Queryable Encryption

Introduced in MongoDB 7.0, [Queryable Encryption](https://www.mongodb.com/docs/manual/core/queryable-encryption/) is another form of in-use encryption. Data is encrypted client-side. Queryable Encryption supports indexed encrypted fields, which are further processed server-side.

### Automatic Queryable Encryption

**Note:**

Automatic queryable encryption requires MongoDB 7.0+ Enterprise or a MongoDB 7.0+ Atlas cluster.

Automatic encryption in Queryable Encryption utilizes `crypt_shared` or `mongocryptd` to automatically encrypt and decrypt data client-side. The data in the `encryptedIndexed` and `encryptedUnindexed` fields will be automatically encrypted on insertion and decrypted when querying on the client side. Additionally, it is possible to query on the `encryptedIndexed` field.

```php
<?php

use MongoDB\BSON\Binary;
use MongoDB\Client;
use MongoDB\Driver\ClientEncryption;

require __DIR__ . '/../../../vendor/autoload.php';

$uri = getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/';

/* Note: this script assumes that the test database is empty and that the key
 * vault collection exists and has a partial, unique index on keyAltNames (as
 * demonstrated in the encryption key management scripts). */

// Generate a secure local key to use for this script
$localKey = new Binary(random_bytes(96));

// Create a client with no encryption options
$client = new Client($uri);

// Create a ClientEncryption object to manage data encryption keys
$clientEncryption = $client->createClientEncryption([
    'keyVaultNamespace' => 'encryption.__keyVault',
    'kmsProviders' => ['local' => ['key' => $localKey]],
]);

/* Create the data encryption keys for this script. Alternatively, the key IDs
 * could be read from a configuration file. */
$keyId1 = $clientEncryption->createDataKey('local');
$keyId2 = $clientEncryption->createDataKey('local');

/* Create another client with automatic encryption enabled. Configure the
 * encrypted collection using the "encryptedFields" option. */
$encryptedClient = new Client($uri, [], [
    'autoEncryption' => [
        'keyVaultNamespace' => 'encryption.__keyVault',
        'kmsProviders' => ['local' => ['key' => $localKey]],
        'encryptedFieldsMap' => [
            'test.coll' => [
                'fields' => [
                    [
                        'path' => 'encryptedIndexed',
                        'bsonType' => 'string',
                        'keyId' => $keyId1,
                        'queries' => ['queryType' => ClientEncryption::QUERY_TYPE_EQUALITY],
                    ],
                    [
                        'path' => 'encryptedUnindexed',
                        'bsonType' => 'string',
                        'keyId' => $keyId2,
                    ],
                ],
            ],
        ],
    ],
]);

/* Create the data collection for this script. The create and drop helpers will
 * infer encryptedFields from the client configuration and manage internal
 * encryption collections automatically. Alternatively, the "encryptedFields"
 * option can also be passed explicitly. */
$encryptedClient->getDatabase('test')->createCollection('coll');
$encryptedCollection = $encryptedClient->getCollection('test', 'coll');

/* Using the encrypted client, insert a document and find it by querying on the
 * encrypted field. Fields will be automatically encrypted and decrypted. */
$encryptedCollection->insertOne([
    '_id' => 1,
    'encryptedIndexed' => 'indexedValue',
    'encryptedUnindexed' => 'unindexedValue',
]);

print_r($encryptedCollection->findOne(['encryptedIndexed' => 'indexedValue']));

/* Using the client configured without encryption, find the same document and
 * observe that fields are not automatically decrypted. */
$unencryptedCollection = $client->getCollection('test', 'coll');

print_r($unencryptedCollection->findOne(['_id' => 1]));

```

### Explicit Queryable Encryption

**Note:**

Explicit queryable encryption requires MongoDB 7.0+.

Explicit encryption in Queryable Encryption is performed using the [MongoDB\Driver\ClientEncryption::encrypt()](https://php.net/mongodb-driver-clientencryption.encrypt) and [decrypt()](https://php.net/mongodb-driver-clientencryption.decrypt) methods. Although values must be explicitly encrypted (e.g. insertions, query criteria), automatic *decryption* for queries is possible by configuring `encryptedFields` on the collection, as demonstrated in the following example:

```php
<?php

use MongoDB\BSON\Binary;
use MongoDB\Client;
use MongoDB\Driver\ClientEncryption;

require __DIR__ . '/../../../vendor/autoload.php';

$uri = getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/';

/* Note: this script assumes that the test database is empty and that the key
 * vault collection exists and has a partial, unique index on keyAltNames (as
 * demonstrated in the encryption key management scripts). */

// Generate a secure local key to use for this script
$localKey = new Binary(random_bytes(96));

// Create a client with no encryption options
$client = new Client($uri);

// Create a ClientEncryption object to manage data encryption keys
$clientEncryption = $client->createClientEncryption([
    'keyVaultNamespace' => 'encryption.__keyVault',
    'kmsProviders' => ['local' => ['key' => $localKey]],
]);

/* Create the data encryption keys. Alternatively, the key IDs could be read
 * from a configuration file. */
$keyId1 = $clientEncryption->createDataKey('local');
$keyId2 = $clientEncryption->createDataKey('local');

// Create another client with automatic encryption disabled
$encryptedClient = new Client($uri, [], [
    'autoEncryption' => [
        'keyVaultNamespace' => 'encryption.__keyVault',
        'kmsProviders' => ['local' => ['key' => $localKey]],
        'bypassQueryAnalysis' => true,
    ],
]);

// Define encrypted fields for the collection
$encryptedFields = [
    'fields' => [
        [
            'path' => 'encryptedIndexed',
            'bsonType' => 'string',
            'keyId' => $keyId1,
            'queries' => ['queryType' => ClientEncryption::QUERY_TYPE_EQUALITY],
        ],
        [
            'path' => 'encryptedUnindexed',
            'bsonType' => 'string',
            'keyId' => $keyId2,
        ],
    ],
];

/* Create the data collection for this script. Specify the "encryptedFields"
 * option to ensure that internal encryption collections are also created. The
 * "encryptedFields" option should also be specified when dropping the
 * collection to ensure that internal encryption collections are dropped. */
$encryptedClient->getDatabase('test')->createCollection('coll', ['encryptedFields' => $encryptedFields]);
$encryptedCollection = $encryptedClient->getCollection('test', 'coll');

// Insert a document with manually encrypted fields
$indexedInsertPayload = $clientEncryption->encrypt('indexedValue', [
    'algorithm' => ClientEncryption::ALGORITHM_INDEXED,
    'contentionFactor' => 1,
    'keyId' => $keyId1,
]);

$unindexedInsertPayload = $clientEncryption->encrypt('unindexedValue', [
    'algorithm' => ClientEncryption::ALGORITHM_UNINDEXED,
    'keyId' => $keyId2,
]);

$encryptedCollection->insertOne([
    '_id' => 1,
    'encryptedIndexed' => $indexedInsertPayload,
    'encryptedUnindexed' => $unindexedInsertPayload,
]);

/* Encrypt the payload for an "equality" query using the same key that was used
 * to encrypt the corresponding insert payload. */
$indexedFindPayload = $clientEncryption->encrypt('indexedValue', [
    'algorithm' => ClientEncryption::ALGORITHM_INDEXED,
    'queryType' => ClientEncryption::QUERY_TYPE_EQUALITY,
    'contentionFactor' => 1,
    'keyId' => $keyId1,
]);

/* Using the client configured with encryption (but not automatic encryption),
 * find the document and observe that the fields are automatically decrypted. */
print_r($encryptedCollection->findOne(['encryptedIndexed' => $indexedFindPayload]));

```
