Client-Side Field Level Encryption
On this page
Overview
In this guide, you can learn how to install and use Client-Side Field Level Encryption (CSFLE) in the MongoDB Java driver.
CSFLE allows you to encrypt specific data fields within a document with your MongoDB client application before sending the data to the server. Starting in MongoDB 4.2 Enterprise, you can perform this client-side encryption automatically.
With CSFLE, your client application encrypts fields client-side without requiring any server-side configuration or directives. CSFLE is useful for situations in which applications must guarantee that unauthorized parties, including server administrators, cannot read the encrypted data.
This guide is a quick introduction to CSFLE using the Java driver. For in-depth information on how CSFLE works, see the CSFLE reference documentation. For a real-world scenario and implementation, see our CSFLE Guide.
Installation
To get started with CSFLE in your client application, you need
the MongoDB Java driver
mongodb-crypt
mongocryptd
if using automatic encryption (Enterprise or Atlas)
mongodb-crypt

The mongodb-crypt
binding is available as a separate JAR. Add it to your project using your desired dependency
management tool.
mongocryptd

mongocryptd
is a binary run as a daemon / process that is used for automatic encryption.
mongodb-crypt
communicates with mongocryptd
to automatically encrypt the information specified by a user-provided
JSON Schema.
For more detailed information on mongocryptd
, see the
mongocryptd reference documentation
Examples
The examples on this page use a local key, but you can also use integrated support for cloud-based key management
services from AWS, Azure, and GCP. Each example program execution creates a new master key in memory and drops the
test.coll
collection.
Tip
In the examples, the in-memory master key is lost when the application finishes running. If you'd like to retain and decrypt documents from previous runs, you can save the local master key to a file for reuse and remove the logic to drop the collection.
Warning
MongoDB recommends using local key management only for testing purposes, and using a remote key management service for production.
Automatic Encryption and Decryption
The following example shows how to configure the AutoEncryptionSettings
instance to create a new key and set the
JSON schema map.
The data in the encryptedField
field is automatically encrypted before insertion, and decrypted when calling find()
on the client side. Querying this collection from a client that isn't configured for CSFLE will return the document in
encrypted form.
The full source is available at ClientSideEncryptionAutoEncryptionSettingsTour.java
Note
Auto encryption requires MongoDB Enterprise or Atlas.
import com.mongodb.AutoEncryptionSettings; import com.mongodb.ClientEncryptionSettings; import com.mongodb.ConnectionString; import com.mongodb.MongoClientSettings; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.vault.DataKeyOptions; import com.mongodb.client.vault.ClientEncryption; import com.mongodb.client.vault.ClientEncryptions; import org.bson.BsonBinary; import org.bson.BsonDocument; import org.bson.Document; import java.security.SecureRandom; import java.util.Base64; import java.util.HashMap; import java.util.Map; public class ClientSideEncryptionAutoEncryptionSettingsTour { /** * Run this main method to see the output of this quick example. * * Requires the mongodb-crypt library in the class path and mongocryptd on the system path. * Assumes the schema has already been created in MongoDB. * * @param args ignored args */ public static void main(final String[] args) { // This would have to be the same master key as was used to create the encryption key final byte[] localMasterKey = new byte[96]; new SecureRandom().nextBytes(localMasterKey); Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>() {{ put("local", new HashMap<String, Object>() {{ put("key", localMasterKey); }}); }}; String keyVaultNamespace = "encryption.__keyVault"; ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://localhost")) .build()) .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); BsonBinary dataKeyId = clientEncryption.createDataKey("local", new DataKeyOptions()); final String base64DataKeyId = Base64.getEncoder().encodeToString(dataKeyId.getData()); final String dbName = "test"; final String collName = "coll"; AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .schemaMap(new HashMap<String, BsonDocument>() {{ put(dbName + "." + collName, // Need a schema that references the new data key BsonDocument.parse("{" + " properties: {" + " encryptedField: {" + " encrypt: {" + " keyId: [{" + " \"$binary\": {" + " \"base64\": \"" + base64DataKeyId + "\"," + " \"subType\": \"04\"" + " }" + " }]," + " bsonType: \"string\"," + " algorithm: \"AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic\"" + " }" + " }" + " }," + " \"bsonType\": \"object\"" + "}")); }}).build(); MongoClientSettings clientSettings = MongoClientSettings.builder() .autoEncryptionSettings(autoEncryptionSettings) .build(); MongoClient mongoClient = MongoClients.create(clientSettings); MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("coll"); collection.drop(); // Clear old data collection.insertOne(new Document("encryptedField", "9876564321")); System.out.println(collection.find().first().toJson()); // release resources mongoClient.close(); } }
Explicit Encryption and Decryption
The prior example demonstrated the automatic CSFLE feature. If your version of MongoDB does not offer automatic CSFLE,
you can perform manual client-side field level encryption, which we call explicit encryption. This method does not
require or use mongocryptd
. The ClientEncryption
class contains methods you can use to perform explicit
encryption.
This example prints out the document in encrypted form, and prints out the explicitly decrypted field value to demonstrate functionality.
The full source is available from ClientSideEncryptionExplicitEncryptionAndDecryptionTour.java
// This would have to be the same master key as was used to create the encryption key final byte[] localMasterKey = new byte[96]; new SecureRandom().nextBytes(localMasterKey); Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>() {{ put("local", new HashMap<String, Object>() {{ put("key", localMasterKey); }}); }}; MongoClientSettings clientSettings = MongoClientSettings.builder().build(); MongoClient mongoClient = MongoClients.create(clientSettings); // Set up the key vault for this example MongoNamespace keyVaultNamespace = new MongoNamespace("encryption.testKeyVault"); MongoCollection<Document> keyVaultCollection = mongoClient .getDatabase(keyVaultNamespace.getDatabaseName()) .getCollection(keyVaultNamespace.getCollectionName()); keyVaultCollection.drop(); // Ensure that two data keys cannot share the same keyAltName. keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"), new IndexOptions().unique(true) .partialFilterExpression(Filters.exists("keyAltNames"))); MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("coll"); collection.drop(); // Clear old data // Create the ClientEncryption instance ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://localhost")) .build()) .keyVaultNamespace(keyVaultNamespace.getFullName()) .kmsProviders(kmsProviders) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); BsonBinary dataKeyId = clientEncryption.createDataKey("local", new DataKeyOptions()); // Explicitly encrypt a field BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)); collection.insertOne(new Document("encryptedField", encryptedFieldValue)); Document doc = collection.find().first(); System.out.println(doc.toJson()); // Explicitly decrypt the field System.out.println( clientEncryption.decrypt(new BsonBinary(doc.get("encryptedField", Binary.class).getData())) );
Explicit Encryption and Auto Decryption
Although automatic encryption requires MongoDB Enterprise or MongoDB Atlas, automatic decryption is available in all MongoDB versions greater than or equal to 4.2.
To configure automatic decryption, set bypassAutoEncryption(true)
in the autoEncryptionSettings
builder.
The following example prints the inserted document out in unencrypted form. The document is automatically decrypted
because autoEncryptionSettings
have been configured.
The full source is available at ClientSideEncryptionExplicitEncryptionOnlyTour.java.
... MongoClientSettings clientSettings = MongoClientSettings.builder() .autoEncryptionSettings(AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace.getFullName()) .kmsProviders(kmsProviders) .bypassAutoEncryption(true) .build()) .build(); MongoClient mongoClient = MongoClients.create(clientSettings); ... // Explicitly encrypt a field BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)); collection.insertOne(new Document("encryptedField", encryptedFieldValue)); // Automatically decrypts the encrypted field. System.out.println(collection.find().first().toJson());