Skip to content

Commit 3835b14

Browse files
committed
Added Client side explicit encryption/decryption example
JAVA-3528
1 parent 94d0eb2 commit 3835b14

File tree

11 files changed

+988
-7
lines changed

11 files changed

+988
-7
lines changed

docs/reference/content/driver-reactive/tutorials/client-side-encryption.md

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,112 @@ AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder()
167167
}}).build();
168168
```
169169

170-
**Coming soon:** An example using the community version and demonstrating explicit encryption/decryption.
170+
#### Explicit Encryption and Decryption
171+
Explicit encryption and decryption is a **MongoDB community** feature and does not use the `mongocryptd` process. Explicit encryption is
172+
provided by the `ClientEncryption` class.
173+
The full code snippet can be found in [`ClientSideEncryptionExplicitEncryptionAndDecryptionTour.java`]({{< srcref "driver-reactive-streams/src/examples/reactivestreams/tour/ClientSideEncryptionAutoEncryptionSettingsTour.java">}}):
174+
175+
```
176+
// This would have to be the same master key as was used to create the encryption key
177+
final byte[] localMasterKey = new byte[96];
178+
new SecureRandom().nextBytes(localMasterKey);
179+
180+
Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>() {{
181+
put("local", new HashMap<String, Object>() {{
182+
put("key", localMasterKey);
183+
}});
184+
}};
185+
186+
MongoNamespace keyVaultNamespace = new MongoNamespace("encryption.testKeyVault");
187+
188+
MongoClientSettings clientSettings = MongoClientSettings.builder().build();
189+
MongoClient mongoClient = MongoClients.create(clientSettings);
190+
191+
// Set up the key vault for this example
192+
MongoCollection<Document> keyVaultCollection = mongoClient
193+
.getDatabase(keyVaultNamespace.getDatabaseName())
194+
.getCollection(keyVaultNamespace.getCollectionName());
195+
196+
ObservableSubscriber<Void> successSubscriber = new OperationSubscriber<>();
197+
keyVaultCollection.drop().subscribe(successSubscriber);
198+
successSubscriber.await();
199+
200+
// Ensure that two data keys cannot share the same keyAltName.
201+
ObservableSubscriber<String> indexSubscriber = new OperationSubscriber<>();
202+
keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"),
203+
new IndexOptions().unique(true)
204+
.partialFilterExpression(Filters.exists("keyAltNames")))
205+
.subscribe(indexSubscriber);
206+
indexSubscriber.await();
207+
208+
MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("coll");
209+
successSubscriber = new OperationSubscriber<>();
210+
collection.drop().subscribe(successSubscriber);
211+
successSubscriber.await();
212+
213+
// Create the ClientEncryption instance
214+
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
215+
.keyVaultMongoClientSettings(MongoClientSettings.builder()
216+
.applyConnectionString(new ConnectionString("mongodb://localhost"))
217+
.build())
218+
.keyVaultNamespace(keyVaultNamespace.getFullName())
219+
.kmsProviders(kmsProviders)
220+
.build();
221+
222+
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
223+
224+
BsonBinary dataKeyId = clientEncryption.createDataKey("local", new DataKeyOptions());
225+
226+
// Explicitly encrypt a field
227+
BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"),
228+
new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId));
229+
230+
ObservableSubscriber<InsertOneResult> insertOneSubscriber = new OperationSubscriber<>();
231+
collection.insertOne(new Document("encryptedField", encryptedFieldValue))
232+
.subscribe(insertOneSubscriber);
233+
insertOneSubscriber.await();
234+
235+
ObservableSubscriber<Document> documentSubscriber = new OperationSubscriber<>();
236+
collection.find().first().subscribe(documentSubscriber);
237+
238+
Document doc = documentSubscriber.get().get(0);
239+
System.out.println(doc.toJson());
240+
241+
// Explicitly decrypt the field
242+
System.out.println(
243+
clientEncryption.decrypt(new BsonBinary(doc.get("encryptedField", Binary.class).getData()))
244+
);
245+
```
246+
#### Explicit Encryption and Auto Decryption
247+
248+
Although automatic encryption requires MongoDB 4.2 enterprise or a MongoDB 4.2 Atlas cluster, automatic decryption is supported for all
249+
users. To configure automatic decryption without automatic encryption set `bypassAutoEncryption(true)`. The full code snippet can be found in [`ClientSideEncryptionExplicitEncryptionOnlyTour.java`]({{< srcref "driver-reactive-streams/src/examples/reactivestreams/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.java">}}):
250+
251+
```
252+
...
253+
MongoClientSettings clientSettings = MongoClientSettings.builder()
254+
.autoEncryptionSettings(AutoEncryptionSettings.builder()
255+
.keyVaultNamespace(keyVaultNamespace.getFullName())
256+
.kmsProviders(kmsProviders)
257+
.bypassAutoEncryption(true)
258+
.build())
259+
.build();
260+
MongoClient mongoClient = MongoClients.create(clientSettings);
261+
262+
...
263+
264+
// Explicitly encrypt a field
265+
BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"),
266+
new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId));
267+
268+
ObservableSubscriber<InsertOneResult> insertOneSubscriber = new OperationSubscriber<>();
269+
collection.insertOne(new Document("encryptedField", encryptedFieldValue))
270+
.subscribe(insertOneSubscriber);
271+
insertOneSubscriber.await();
272+
273+
ObservableSubscriber<Document> documentSubscriber = new OperationSubscriber<>();
274+
collection.find().first().subscribe(documentSubscriber);
275+
276+
Document doc = documentSubscriber.get().get(0);
277+
System.out.println(doc.toJson());
278+
```

docs/reference/content/driver-scala/tutorials/client-side-encryption.md

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,91 @@ import tour.Helpers._
162162
.build()
163163
```
164164

165-
**Coming soon:** An example using the community version and demonstrating explicit encryption/decryption.
165+
#### Explicit Encryption and Decryption
166+
Explicit encryption and decryption is a **MongoDB community** feature and does not use the `mongocryptd` process. Explicit encryption is
167+
provided by the `ClientEncryption` class.
168+
The full code snippet can be found in [`ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala`]({{< srcref "driver-scala/src/it/scala/tour/ClientSideEncryptionAutoEncryptionSettingsTour.scala">}}):
169+
170+
```
171+
// This would have to be the same master key as was used to create the encryption key
172+
val localMasterKey = new Array[Byte](96)
173+
new SecureRandom().nextBytes(localMasterKey)
174+
175+
val kmsProviders = Map("local" -> Map[String, AnyRef]("key" -> localMasterKey).asJava).asJava
176+
177+
val keyVaultNamespace = new MongoNamespace("encryption.testKeyVault")
178+
179+
val clientSettings = MongoClientSettings.builder().build()
180+
val mongoClient = MongoClient(clientSettings)
181+
182+
// Set up the key vault for this example
183+
val keyVaultCollection = mongoClient.getDatabase(keyVaultNamespace.getDatabaseName)
184+
.getCollection(keyVaultNamespace.getCollectionName)
185+
keyVaultCollection.drop().headResult()
186+
187+
// Ensure that two data keys cannot share the same keyAltName.
188+
keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"), new IndexOptions().unique(true)
189+
.partialFilterExpression(Filters.exists("keyAltNames")))
190+
191+
val collection = mongoClient.getDatabase("test").getCollection("coll")
192+
collection.drop().headResult()
193+
194+
// Create the ClientEncryption instance
195+
val clientEncryptionSettings = ClientEncryptionSettings
196+
.builder()
197+
.keyVaultMongoClientSettings(
198+
MongoClientSettings.builder()
199+
.applyConnectionString(ConnectionString("mongodb://localhost")).build()
200+
)
201+
.keyVaultNamespace(keyVaultNamespace.getFullName)
202+
.kmsProviders(kmsProviders)
203+
.build()
204+
205+
val clientEncryption = ClientEncryptions.create(clientEncryptionSettings)
206+
207+
val dataKeyId = clientEncryption.createDataKey("local", DataKeyOptions()).headResult()
208+
209+
// Explicitly encrypt a field
210+
val encryptedFieldValue = clientEncryption.encrypt(BsonString("123456789"),
211+
EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId))
212+
.headResult()
213+
214+
collection.insertOne(Document("encryptedField" -> encryptedFieldValue)).headResult()
215+
216+
val doc = collection.find.first().headResult()
217+
println(doc.toJson())
218+
219+
// Explicitly decrypt the field
220+
println(
221+
clientEncryption.decrypt(doc.get[BsonBinary]("encryptedField").get).headResult()
222+
)
223+
```
224+
225+
#### Explicit Encryption and Auto Decryption
226+
227+
Although automatic encryption requires MongoDB 4.2 enterprise or a MongoDB 4.2 Atlas cluster, automatic decryption is supported for all
228+
users. To configure automatic decryption without automatic encryption set `bypassAutoEncryption(true)`. The full code snippet can be found in [`ClientSideEncryptionExplicitEncryptionOnlyTour.scala`]({{< srcref "driver-scala/src/it/scala/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.scala">}}):
229+
230+
```
231+
...
232+
val clientSettings = MongoClientSettings.builder()
233+
.autoEncryptionSettings(AutoEncryptionSettings.builder()
234+
.keyVaultNamespace(keyVaultNamespace.getFullName)
235+
.kmsProviders(kmsProviders)
236+
.bypassAutoEncryption(true)
237+
.build())
238+
.build()
239+
val mongoClient = MongoClients.create(clientSettings)
240+
241+
...
242+
243+
// Explicitly encrypt a field
244+
val encryptedFieldValue = clientEncryption.encrypt(BsonString("123456789"),
245+
EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId))
246+
.headResult()
247+
248+
collection.insertOne(Document("encryptedField" -> encryptedFieldValue)).headResult()
249+
250+
val doc = collection.find.first().headResult()
251+
println(doc.toJson())
252+
```

docs/reference/content/driver/tutorials/client-side-encryption.md

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ There is a separate jar file containing`libmongocrypt` bindings.
3636
`libmongocrypt` requires the `mongocryptd` daemon / process to be running. A specific daemon / process uri can be configured in the
3737
`AutoEncryptionSettings` class by setting `mongocryptdURI` in the `extraOptions`.
3838

39-
More information about mongocryptd will soon be available from the official documentation.
39+
For more information about mongocryptd see the [official documentation](https://docs.mongodb.com/manual/core/security-client-side-encryption/).
4040

4141

4242
### Examples
@@ -157,4 +157,92 @@ AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder()
157157
}}).build();
158158
```
159159

160-
**Coming soon:** An example using the community version and demonstrating explicit encryption/decryption.
160+
#### Explicit Encryption and Decryption
161+
Explicit encryption and decryption is a **MongoDB community** feature and does not use the `mongocryptd` process. Explicit encryption is
162+
provided by the `ClientEncryption` class.
163+
The full code snippet can be found in [`ClientSideEncryptionExplicitEncryptionAndDecryptionTour.java`]({{< srcref "driver-sync/src/examples/tour/ClientSideEncryptionExplicitEncryptionAndDecryptionTour.java">}}):
164+
165+
```
166+
// This would have to be the same master key as was used to create the encryption key
167+
final byte[] localMasterKey = new byte[96];
168+
new SecureRandom().nextBytes(localMasterKey);
169+
170+
Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>() {{
171+
put("local", new HashMap<String, Object>() {{
172+
put("key", localMasterKey);
173+
}});
174+
}};
175+
176+
MongoClientSettings clientSettings = MongoClientSettings.builder().build();
177+
MongoClient mongoClient = MongoClients.create(clientSettings);
178+
179+
// Set up the key vault for this example
180+
MongoNamespace keyVaultNamespace = new MongoNamespace("encryption.testKeyVault");
181+
MongoCollection<Document> keyVaultCollection = mongoClient
182+
.getDatabase(keyVaultNamespace.getDatabaseName())
183+
.getCollection(keyVaultNamespace.getCollectionName());
184+
keyVaultCollection.drop();
185+
186+
// Ensure that two data keys cannot share the same keyAltName.
187+
keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"),
188+
new IndexOptions().unique(true)
189+
.partialFilterExpression(Filters.exists("keyAltNames")));
190+
191+
MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("coll");
192+
collection.drop(); // Clear old data
193+
194+
// Create the ClientEncryption instance
195+
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
196+
.keyVaultMongoClientSettings(MongoClientSettings.builder()
197+
.applyConnectionString(new ConnectionString("mongodb://localhost"))
198+
.build())
199+
.keyVaultNamespace(keyVaultNamespace.getFullName())
200+
.kmsProviders(kmsProviders)
201+
.build();
202+
203+
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
204+
205+
BsonBinary dataKeyId = clientEncryption.createDataKey("local", new DataKeyOptions());
206+
207+
// Explicitly encrypt a field
208+
BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"),
209+
new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId));
210+
211+
collection.insertOne(new Document("encryptedField", encryptedFieldValue));
212+
213+
Document doc = collection.find().first();
214+
System.out.println(doc.toJson());
215+
216+
// Explicitly decrypt the field
217+
System.out.println(
218+
clientEncryption.decrypt(new BsonBinary(doc.get("encryptedField", Binary.class).getData()))
219+
);
220+
```
221+
222+
#### Explicit Encryption and Auto Decryption
223+
224+
Although automatic encryption requires MongoDB 4.2 enterprise or a MongoDB 4.2 Atlas cluster, automatic decryption is supported for all
225+
users. To configure automatic decryption without automatic encryption set `bypassAutoEncryption(true)`. The full code snippet can be found in [`ClientSideEncryptionExplicitEncryptionOnlyTour.java`]({{< srcref "driver-sync/src/examples/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.java">}}):
226+
227+
```
228+
...
229+
MongoClientSettings clientSettings = MongoClientSettings.builder()
230+
.autoEncryptionSettings(AutoEncryptionSettings.builder()
231+
.keyVaultNamespace(keyVaultNamespace.getFullName())
232+
.kmsProviders(kmsProviders)
233+
.bypassAutoEncryption(true)
234+
.build())
235+
.build();
236+
MongoClient mongoClient = MongoClients.create(clientSettings);
237+
238+
...
239+
240+
// Explicitly encrypt a field
241+
BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"),
242+
new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId));
243+
244+
collection.insertOne(new Document("encryptedField", encryptedFieldValue));
245+
246+
// Automatically decrypts the encrypted field.
247+
System.out.println(collection.find().first().toJson());
248+
```

0 commit comments

Comments
 (0)