Skip to content

Commit 02bd585

Browse files
committed
Merge pull request #716
2 parents f4406d7 + bb48f77 commit 02bd585

File tree

2 files changed

+242
-0
lines changed

2 files changed

+242
-0
lines changed

docs/tutorial.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Tutorials
1010
/tutorial/commands
1111
/tutorial/custom-types
1212
/tutorial/decimal128
13+
/tutorial/client-side-encryption
1314
/tutorial/gridfs
1415
/tutorial/indexes
1516
/tutorial/tailable-cursor
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
======================
2+
Client-Side Encryption
3+
======================
4+
5+
.. default-domain:: mongodb
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 1
11+
:class: singlecol
12+
13+
Client-Side Field Level Encryption allows administrators and developers to
14+
encrypt specific data fields in addition to other MongoDB encryption features.
15+
16+
17+
Automatic Encryption and Decryption
18+
-----------------------------------
19+
20+
.. note::
21+
22+
Auto encryption is an enterprise only feature.
23+
24+
The following example uses a local key, however using AWS Key Management Service
25+
is also an option. The data in the ``encryptedField`` field is automatically
26+
encrypted on insertion and decrypted when querying on the client side.
27+
28+
.. code-block:: php
29+
30+
<?php
31+
32+
use MongoDB\BSON\Binary;
33+
use MongoDB\Client;
34+
35+
$localKey = new Binary('<binary key data (96 bytes)>', Binary::TYPE_GENERIC);
36+
37+
$encryptionOpts = [
38+
'keyVaultNamespace' => 'admin.datakeys',
39+
'kmsProviders' => [
40+
'local' => ['key' => $localKey],
41+
],
42+
];
43+
44+
$client = new Client('mongodb://127.0.0.1');
45+
$clientEncryption = $client->createClientEncryption($encryptionOpts);
46+
47+
$database = $client->selectDatabase('test');
48+
$database->dropCollection('coll'); // remove old data
49+
50+
// Create new key in the key vault and store its ID for later use
51+
$keyId = $clientEncryption->createDataKey('local');
52+
53+
$database->createCollection('coll', [
54+
'validator' => [
55+
'$jsonSchema' => [
56+
'bsonType' => 'object',
57+
'properties' => [
58+
'encryptedField' => [
59+
'encrypt' => [
60+
'keyId' => [$keyId],
61+
'bsonType' => 'string',
62+
'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
63+
],
64+
],
65+
],
66+
],
67+
],
68+
]);
69+
70+
$encryptedClient = new Client('mongodb://127.0.0.1', [], ['autoEncryption' => $encryptionOpts]);
71+
72+
$collection = $encryptedClient->selectCollection('test', 'coll');
73+
74+
$collection->insertOne(['encryptedField' => '123456789']);
75+
76+
var_dump($collection->findOne([]));
77+
78+
79+
Specifying an Explicit Schema for Encryption
80+
--------------------------------------------
81+
82+
The following example shows how to create a new key and store it in the key
83+
vault collection. The encrypted client configures an explicit schema for
84+
encryption using the newly created key.
85+
86+
.. note::
87+
88+
Supplying a ``schemaMap`` provides more security than relying on JSON schemas
89+
obtained from the server. It protects against a malicious server advertising
90+
a false JSON schema, which could trick the client into sending unencrypted
91+
data that should be encrypted.
92+
93+
.. code-block:: php
94+
95+
<?php
96+
97+
use MongoDB\BSON\Binary;
98+
use MongoDB\Client;
99+
use MongoDB\Driver\ClientEncryption;
100+
101+
$localKey = new Binary('<binary key data (96 bytes)>', Binary::TYPE_GENERIC);
102+
103+
$clientEncryptionOpts = [
104+
'keyVaultNamespace' => 'admin.datakeys',
105+
'kmsProviders' => [
106+
'local' => ['key' => $localKey],
107+
],
108+
];
109+
110+
$client = new Client();
111+
$clientEncryption = $client->createClientEncryption($clientEncryptionOpts);
112+
113+
// Create new key in the key vault and store its ID for later use
114+
$keyId = $clientEncryption->createDataKey('local');
115+
116+
$autoEncryptionOpts = [
117+
'keyVaultNamespace' => 'admin.datakeys',
118+
'kmsProviders' => [
119+
'local' => ['key' => $localKey],
120+
],
121+
'schemaMap' => [
122+
'test.coll' => [
123+
'bsonType' => 'object',
124+
'properties' => [
125+
'encryptedField' => [
126+
'encrypt' => [
127+
'keyId' => [$keyId],
128+
'bsonType' => 'string',
129+
'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
130+
],
131+
],
132+
],
133+
],
134+
],
135+
];
136+
137+
$encryptedClient = new Client('mongodb://127.0.0.1', [], ['autoEncryption' => $autoEncryptionOpts]);
138+
139+
$collection = $encryptedClient->selectCollection('test', 'coll');
140+
$collection->drop(); // clear old data
141+
142+
$collection->insertOne(['encryptedField' => '123456789']);
143+
144+
var_dump($collection->findOne([]));
145+
146+
147+
Manually Encrypting and Decrypting Values
148+
-----------------------------------------
149+
150+
In the MongoDB Community Edition, you will have to manually encrypt and decrypt
151+
values before storing them in the database. The following example assumes that
152+
you have already created an encryption key in the key vault collection and
153+
explicitly encrypts and decrypts values in the document.
154+
155+
.. code-block:: php
156+
157+
<?php
158+
159+
use MongoDB\BSON\Binary;
160+
use MongoDB\Client;
161+
use MongoDB\Driver\ClientEncryption;
162+
163+
$localKey = new Binary('<binary key data (96 bytes)>', Binary::TYPE_GENERIC);
164+
165+
$clientEncryptionOpts = [
166+
'keyVaultNamespace' => 'admin.datakeys',
167+
'kmsProviders' => [
168+
'local' => ['key' => $localKey],
169+
],
170+
];
171+
172+
$client = new Client();
173+
$clientEncryption = $client->createClientEncryption($clientEncryptionOpts);
174+
175+
// Create new key in the key vault and store its ID for later use
176+
$keyId = $clientEncryption->createDataKey('local');
177+
178+
$collection = $client->selectCollection('test', 'coll');
179+
$collection->drop(); // clear old data
180+
181+
$encryptionOpts = [
182+
'keyId' => $keyId,
183+
'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
184+
];
185+
$encryptedValue = $clientEncryption->encrypt('123456789', $encryptionOpts);
186+
187+
$collection->insertOne(['encryptedField' => $encryptedValue]);
188+
189+
$document = $collection->findOne();
190+
var_dump($clientEncryption->decrypt($document->encryptedField));
191+
192+
193+
Referencing Encryption Keys by an Alternative Name
194+
--------------------------------------------------
195+
196+
While it is possible to create an encryption key every time data is encrypted,
197+
this is not the recommended approach. Instead, you should create your encryption
198+
keys depending on your use-case, e.g. by creating a user-specific encryption
199+
key. To reference keys in your software, you can use the keyAltName attribute
200+
specified when creating the key. The following example creates an encryption key
201+
with an alternative name, which could be done when deploying the application.
202+
The software then encrypts data by referencing the key by its alternative name.
203+
204+
.. code-block:: php
205+
206+
<?php
207+
208+
use MongoDB\BSON\Binary;
209+
use MongoDB\Client;
210+
use MongoDB\Driver\ClientEncryption;
211+
212+
$localKey = new Binary('<binary key data (96 bytes)>', Binary::TYPE_GENERIC);
213+
214+
$clientEncryptionOpts = [
215+
'keyVaultNamespace' => 'admin.datakeys',
216+
'kmsProviders' => [
217+
'local' => ['key' => $localKey],
218+
],
219+
];
220+
221+
$client = new Client();
222+
$clientEncryption = $client->createClientEncryption($clientEncryptionOpts);
223+
224+
// Create an encryption key with an alternative name. This could be done when
225+
// deploying the application
226+
$keyId = $clientEncryption->createDataKey('local', ['keyAltNames' => ['altname']]);
227+
228+
$collection = $client->selectCollection('test', 'coll');
229+
$collection->drop(); // clear old data
230+
231+
// Reference the encryption key we created earlier by its alternative name
232+
$encryptionOpts = [
233+
'keyAltName' => 'altname',
234+
'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
235+
];
236+
$encryptedValue = $clientEncryption->encrypt('123456789', $encryptionOpts);
237+
238+
$collection->insertOne(['encryptedField' => $encryptedValue]);
239+
240+
$document = $collection->findOne();
241+
var_dump($clientEncryption->decrypt($document->encryptedField));

0 commit comments

Comments
 (0)