Skip to content

Commit 8850a9b

Browse files
CSHARP-2869: Update FLE documentation for community version demonstrating explicit encryption/decryption.
1 parent 49cac7f commit 8850a9b

File tree

2 files changed

+308
-5
lines changed

2 files changed

+308
-5
lines changed

Docs/reference/content/reference/driver/crud/client_side_encryption.md

Lines changed: 154 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ documentation.
4040

4141
## Examples
4242

43+
### Automatic client-side encryption
44+
4345
The following is a sample app that assumes the **key** and **schema** have
4446
already been created in MongoDB. The example uses a local key, however using AWS
4547
Key Management Service is also an option. The data in the `encryptedField` field
@@ -132,11 +134,13 @@ namespace MongoDB.Driver.Examples
132134
keyVaultNamespace,
133135
kmsProviders);
134136

135-
var clientEncryption = new ClientEncryption(clientEncryptionSettings);
136-
var dataKeyId = clientEncryption.CreateDataKey("local", new DataKeyOptions(), CancellationToken.None);
137-
var base64DataKeyId = Convert.ToBase64String(GuidConverter.ToBytes(dataKeyId, GuidRepresentation.Standard));
138-
clientEncryption.Dispose();
137+
Guid dataKeyId;
138+
using (var clientEncryption = new ClientEncryption(clientEncryptionSettings))
139+
{
140+
dataKeyId = clientEncryption.CreateDataKey("local", new DataKeyOptions(), CancellationToken.None);
141+
}
139142

143+
var base64DataKeyId = Convert.ToBase64String(GuidConverter.ToBytes(dataKeyId, GuidRepresentation.Standard));
140144
var collectionNamespace = CollectionNamespace.FromFullName("test.coll");
141145

142146
var schemaMap = $@"{{
@@ -181,4 +185,149 @@ namespace MongoDB.Driver.Examples
181185
}
182186
```
183187

184-
**Coming soon:** An example using the community version and demonstrating explicit encryption/decryption.
188+
### Explicit Encryption and Decryption
189+
190+
Explicit encryption and decryption is a **MongoDB Community Server** feature and does not use the `mongocryptd` process. Explicit encryption is provided by the `ClientEncryption` class. The following example has been adapted from [`ExplicitEncryptionExamples.cs`](https://github.com/mongodb/mongo-csharp-driver/blob/master/tests/MongoDB.Driver.Examples/ExplicitEncryptionExamples.cs):
191+
192+
```csharp
193+
using System;
194+
using System.Collections.Generic;
195+
using System.Threading;
196+
using MongoDB.Driver.Encryption;
197+
using MongoDB.Libmongocrypt;
198+
199+
namespace MongoDB.Driver.Examples
200+
{
201+
public class ExplicitEncryptionExamples
202+
{
203+
private const string LocalMasterKey = "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk";
204+
205+
public static void Main(string[] args)
206+
{
207+
var localMasterKey = Convert.FromBase64String(LocalMasterKey);
208+
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
209+
var localKey = new Dictionary<string, object>
210+
{
211+
{ "key", localMasterKey }
212+
};
213+
kmsProviders.Add("local", localKey);
214+
215+
var keyVaultNamespace = CollectionNamespace.FromFullName("admin.datakeys");
216+
var keyVaultClient = new MongoClient("mongodb://localhost");
217+
var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);
218+
keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);
219+
220+
// Create the ClientEncryption instance
221+
var clientEncryptionSettings = new ClientEncryptionOptions(
222+
keyVaultClient,
223+
keyVaultNamespace,
224+
kmsProviders);
225+
using (var clientEncryption = new ClientEncryption(clientEncryptionSettings))
226+
{
227+
var dataKeyId = clientEncryption.CreateDataKey(
228+
"local",
229+
new DataKeyOptions(),
230+
CancellationToken.None);
231+
232+
var originalString = "123456789";
233+
Console.WriteLine($"Original string {originalString}.");
234+
235+
// Explicitly encrypt a field
236+
var encryptOptions = new EncryptOptions(
237+
EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
238+
keyId: dataKeyId);
239+
var encryptedFieldValue = clientEncryption.Encrypt(
240+
originalString,
241+
encryptOptions,
242+
CancellationToken.None);
243+
Console.WriteLine($"Encrypted value {encryptedFieldValue}.");
244+
245+
// Explicitly decrypt the field
246+
var decryptedValue = clientEncryption.Decrypt(encryptedFieldValue, CancellationToken.None);
247+
Console.WriteLine($"Decrypted value {decryptedValue}.");
248+
}
249+
}
250+
}
251+
}
252+
```
253+
254+
### Explicit Encryption and Auto Decryption
255+
256+
Although automatic encryption requires MongoDB 4.2 Enterprise Server or a MongoDB 4.2 Atlas cluster, automatic decryption is supported for all users. To configure automatic decryption without automatic encryption set `bypassAutoEncryption=true`. The following example has been adapted from [`ExplicitEncryptionExamples.cs`](https://github.com/mongodb/mongo-csharp-driver/blob/master/tests/MongoDB.Driver.Examples/ExplicitEncryptionExamples.cs):
257+
258+
```csharp
259+
using System;
260+
using System.Collections.Generic;
261+
using System.Threading;
262+
using MongoDB.Bson;
263+
using MongoDB.Driver.Encryption;
264+
using MongoDB.Libmongocrypt;
265+
266+
namespace MongoDB.Driver.Examples
267+
{
268+
public class ExplicitEncryptionAndAutoDecryptionExamples
269+
{
270+
private const string LocalMasterKey = "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk";
271+
272+
public static void Main(string[] args)
273+
{
274+
var localMasterKey = Convert.FromBase64String(LocalMasterKey);
275+
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
276+
var localKey = new Dictionary<string, object>
277+
{
278+
{ "key", localMasterKey }
279+
};
280+
kmsProviders.Add("local", localKey);
281+
282+
var keyVaultNamespace = CollectionNamespace.FromFullName("admin.datakeys");
283+
var collectionNamespace = CollectionNamespace.FromFullName("test.coll");
284+
var autoEncryptionOptions = new AutoEncryptionOptions(
285+
keyVaultNamespace,
286+
kmsProviders,
287+
bypassAutoEncryption: true);
288+
var clientSettings = MongoClientSettings.FromConnectionString("mongodb://localhost");
289+
clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
290+
var mongoClient = new MongoClient(clientSettings);
291+
var database = mongoClient.GetDatabase(collectionNamespace.DatabaseNamespace.DatabaseName);
292+
database.DropCollection(collectionNamespace.CollectionName);
293+
var collection = database.GetCollection<BsonDocument>(collectionNamespace.CollectionName);
294+
295+
var keyVaultClient = new MongoClient("mongodb://localhost");
296+
var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);
297+
keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);
298+
299+
// Create the ClientEncryption instance
300+
var clientEncryptionSettings = new ClientEncryptionOptions(
301+
keyVaultClient,
302+
keyVaultNamespace,
303+
kmsProviders);
304+
using (var clientEncryption = new ClientEncryption(clientEncryptionSettings))
305+
{
306+
var dataKeyId = clientEncryption.CreateDataKey(
307+
"local",
308+
new DataKeyOptions(),
309+
CancellationToken.None);
310+
311+
var originalString = "123456789";
312+
Console.WriteLine($"Original string {originalString}.");
313+
314+
// Explicitly encrypt a field
315+
var encryptOptions = new EncryptOptions(
316+
EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
317+
keyId: dataKeyId);
318+
var encryptedFieldValue = clientEncryption.Encrypt(
319+
originalString,
320+
encryptOptions,
321+
CancellationToken.None);
322+
Console.WriteLine($"Encrypted value {encryptedFieldValue}.");
323+
324+
collection.InsertOne(new BsonDocument("encryptedField", encryptedFieldValue));
325+
326+
// Automatically decrypts the encrypted field.
327+
var decryptedValue = collection.Find(FilterDefinition<BsonDocument>.Empty).First();
328+
Console.WriteLine($"Decrypted document {decryptedValue.ToJson()}.");
329+
}
330+
}
331+
}
332+
}
333+
```
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/* Copyright 2020-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using System.Threading;
19+
using MongoDB.Bson;
20+
using MongoDB.Driver.Core.Misc;
21+
using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
22+
using MongoDB.Driver.Encryption;
23+
using MongoDB.Libmongocrypt;
24+
using Xunit;
25+
using Xunit.Abstractions;
26+
27+
namespace MongoDB.Driver.Examples
28+
{
29+
public class ExplicitEncryptionExamples
30+
{
31+
private const string LocalMasterKey = "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk";
32+
33+
private readonly ITestOutputHelper _output;
34+
35+
public ExplicitEncryptionExamples(ITestOutputHelper output)
36+
{
37+
_output = output;
38+
}
39+
40+
[Fact]
41+
public void ClientSideExplicitEncryptionAndDecryptionTour()
42+
{
43+
RequireServer.Check().Supports(Feature.ClientSideEncryption);
44+
45+
var localMasterKey = Convert.FromBase64String(LocalMasterKey);
46+
47+
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
48+
var localKey = new Dictionary<string, object>
49+
{
50+
{ "key", localMasterKey }
51+
};
52+
kmsProviders.Add("local", localKey);
53+
54+
var keyVaultNamespace = CollectionNamespace.FromFullName("admin.datakeys");
55+
var keyVaultClient = new MongoClient("mongodb://localhost");
56+
var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);
57+
keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);
58+
59+
// Create the ClientEncryption instance
60+
var clientEncryptionSettings = new ClientEncryptionOptions(
61+
keyVaultClient,
62+
keyVaultNamespace,
63+
kmsProviders);
64+
using (var clientEncryption = new ClientEncryption(clientEncryptionSettings))
65+
{
66+
var dataKeyId = clientEncryption.CreateDataKey(
67+
"local",
68+
new DataKeyOptions(),
69+
CancellationToken.None);
70+
71+
var originalString = "123456789";
72+
_output.WriteLine($"Original string {originalString}.");
73+
74+
// Explicitly encrypt a field
75+
var encryptOptions = new EncryptOptions(
76+
EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
77+
keyId: dataKeyId);
78+
var encryptedFieldValue = clientEncryption.Encrypt(
79+
originalString,
80+
encryptOptions,
81+
CancellationToken.None);
82+
_output.WriteLine($"Encrypted value {encryptedFieldValue}.");
83+
84+
// Explicitly decrypt the field
85+
var decryptedValue = clientEncryption.Decrypt(encryptedFieldValue, CancellationToken.None);
86+
_output.WriteLine($"Decrypted value {decryptedValue}.");
87+
}
88+
}
89+
90+
[Fact]
91+
public void ClientSideExplicitEncryptionAndAutoDecryptionTour()
92+
{
93+
RequireServer.Check().Supports(Feature.ClientSideEncryption);
94+
95+
var localMasterKey = Convert.FromBase64String(LocalMasterKey);
96+
97+
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
98+
var localKey = new Dictionary<string, object>
99+
{
100+
{ "key", localMasterKey }
101+
};
102+
kmsProviders.Add("local", localKey);
103+
104+
var keyVaultNamespace = CollectionNamespace.FromFullName("admin.datakeys");
105+
var collectionNamespace = CollectionNamespace.FromFullName("test.coll");
106+
var autoEncryptionOptions = new AutoEncryptionOptions(
107+
keyVaultNamespace,
108+
kmsProviders,
109+
bypassAutoEncryption: true);
110+
var clientSettings = MongoClientSettings.FromConnectionString("mongodb://localhost");
111+
clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
112+
var mongoClient = new MongoClient(clientSettings);
113+
var database = mongoClient.GetDatabase(collectionNamespace.DatabaseNamespace.DatabaseName);
114+
database.DropCollection(collectionNamespace.CollectionName);
115+
var collection = database.GetCollection<BsonDocument>(collectionNamespace.CollectionName);
116+
117+
var keyVaultClient = new MongoClient("mongodb://localhost");
118+
var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);
119+
keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);
120+
121+
// Create the ClientEncryption instance
122+
var clientEncryptionSettings = new ClientEncryptionOptions(
123+
keyVaultClient,
124+
keyVaultNamespace,
125+
kmsProviders);
126+
using (var clientEncryption = new ClientEncryption(clientEncryptionSettings))
127+
{
128+
var dataKeyId = clientEncryption.CreateDataKey(
129+
"local",
130+
new DataKeyOptions(),
131+
CancellationToken.None);
132+
133+
var originalString = "123456789";
134+
_output.WriteLine($"Original string {originalString}.");
135+
136+
// Explicitly encrypt a field
137+
var encryptOptions = new EncryptOptions(
138+
EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
139+
keyId: dataKeyId);
140+
var encryptedFieldValue = clientEncryption.Encrypt(
141+
originalString,
142+
encryptOptions,
143+
CancellationToken.None);
144+
_output.WriteLine($"Encrypted value {encryptedFieldValue}.");
145+
146+
collection.InsertOne(new BsonDocument("encryptedField", encryptedFieldValue));
147+
148+
// Automatically decrypts the encrypted field.
149+
var decryptedValue = collection.Find(FilterDefinition<BsonDocument>.Empty).First();
150+
_output.WriteLine($"Decrypted document {decryptedValue.ToJson()}.");
151+
}
152+
}
153+
}
154+
}

0 commit comments

Comments
 (0)