Skip to content

Commit cae375b

Browse files
committed
Added Client side explicit encryption/decryption example
JAVA-3528
1 parent 9751546 commit cae375b

File tree

3 files changed

+212
-3
lines changed

3 files changed

+212
-3
lines changed

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

Lines changed: 93 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,95 @@ 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+
BsonString decryptedFieldValue = clientEncryption.decrypt(
218+
new BsonBinary(doc.get("encryptedField", Binary.class).getData())).asString();
219+
System.out.println(decryptedFieldValue.getValue());
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+
Document doc = collection.find().first();
248+
System.out.println(doc.toJson());
249+
System.out.println(doc.get("encryptedField"));
250+
251+
```

driver-sync/src/examples/tour/ClientSideEncryptionExplicitEncryptionAndDecryptionTour.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ public static void main(final String[] args) {
102102
System.out.println(doc.toJson());
103103

104104
// Explicitly decrypt the field
105-
System.out.println(clientEncryption.decrypt(new BsonBinary(doc.get("encryptedField", Binary.class).getData())));
105+
BsonString decryptedFieldValue = clientEncryption.decrypt(new BsonBinary(doc.get("encryptedField", Binary.class).getData()))
106+
.asString();
107+
System.out.println(decryptedFieldValue.getValue());
106108

107109
// release resources
108110
clientEncryption.close();
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package tour;
18+
19+
import com.mongodb.AutoEncryptionSettings;
20+
import com.mongodb.ClientEncryptionSettings;
21+
import com.mongodb.ConnectionString;
22+
import com.mongodb.MongoClientSettings;
23+
import com.mongodb.MongoNamespace;
24+
import com.mongodb.client.MongoClient;
25+
import com.mongodb.client.MongoClients;
26+
import com.mongodb.client.MongoCollection;
27+
import com.mongodb.client.model.Filters;
28+
import com.mongodb.client.model.IndexOptions;
29+
import com.mongodb.client.model.Indexes;
30+
import com.mongodb.client.model.vault.DataKeyOptions;
31+
import com.mongodb.client.model.vault.EncryptOptions;
32+
import com.mongodb.client.vault.ClientEncryption;
33+
import com.mongodb.client.vault.ClientEncryptions;
34+
import org.bson.BsonBinary;
35+
import org.bson.BsonString;
36+
import org.bson.Document;
37+
38+
import java.security.SecureRandom;
39+
import java.util.HashMap;
40+
import java.util.Map;
41+
42+
/**
43+
* ClientSideEncryption explicit encryption and decryption tour
44+
*/
45+
public class ClientSideEncryptionExplicitEncryptionOnlyTour {
46+
47+
/**
48+
* Run this main method to see the output of this quick example.
49+
*
50+
* @param args ignored args
51+
*/
52+
public static void main(final String[] args) {
53+
54+
// This would have to be the same master key as was used to create the encryption key
55+
final byte[] localMasterKey = new byte[96];
56+
new SecureRandom().nextBytes(localMasterKey);
57+
58+
Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>() {{
59+
put("local", new HashMap<String, Object>() {{
60+
put("key", localMasterKey);
61+
}});
62+
}};
63+
64+
MongoNamespace keyVaultNamespace = new MongoNamespace("encryption.testKeyVault");
65+
66+
MongoClientSettings clientSettings = MongoClientSettings.builder()
67+
.autoEncryptionSettings(AutoEncryptionSettings.builder()
68+
.keyVaultNamespace(keyVaultNamespace.getFullName())
69+
.kmsProviders(kmsProviders)
70+
.bypassAutoEncryption(true)
71+
.build())
72+
.build();
73+
MongoClient mongoClient = MongoClients.create(clientSettings);
74+
75+
// Set up the key vault for this example
76+
MongoCollection<Document> keyVaultCollection = mongoClient.getDatabase(keyVaultNamespace.getDatabaseName())
77+
.getCollection(keyVaultNamespace.getCollectionName());
78+
keyVaultCollection.drop();
79+
80+
// Ensure that two data keys cannot share the same keyAltName.
81+
keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"),
82+
new IndexOptions().unique(true)
83+
.partialFilterExpression(Filters.exists("keyAltNames")));
84+
85+
MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("coll");
86+
collection.drop(); // Clear old data
87+
88+
// Create the ClientEncryption instance
89+
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
90+
.keyVaultMongoClientSettings(MongoClientSettings.builder()
91+
.applyConnectionString(new ConnectionString("mongodb://localhost"))
92+
.build())
93+
.keyVaultNamespace(keyVaultNamespace.getFullName())
94+
.kmsProviders(kmsProviders)
95+
.build();
96+
97+
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
98+
99+
BsonBinary dataKeyId = clientEncryption.createDataKey("local", new DataKeyOptions());
100+
101+
// Explicitly encrypt a field
102+
BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"),
103+
new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId));
104+
105+
collection.insertOne(new Document("encryptedField", encryptedFieldValue));
106+
107+
// Automatically decrypts the encrypted field.
108+
Document doc = collection.find().first();
109+
System.out.println(doc.toJson());
110+
System.out.println(doc.get("encryptedField"));
111+
112+
// release resources
113+
clientEncryption.close();
114+
mongoClient.close();
115+
}
116+
}

0 commit comments

Comments
 (0)