Docs Menu
Docs Home
/
MongoDB Manual
/ / / /

Quick Start

On this page

  • Overview
  • Before You Get Started
  • Procedure
  • Assign Your Application Variables
  • Create your Encrypted Collection
  • Insert a Document with Encrypted Fields
  • Query on an Encrypted Field
  • Learn More

This guide shows you how to build an application that implements the MongoDB Queryable Encryption feature to automatically encrypt and decrypt document fields.

Select your driver language in the dropdown menu on the right to learn how to create an application that automatically encrypts and decrypts document fields.

Important

Do Not Use this Sample Application In Production

Because the instructions in this tutorial include storing an encryption key in an insecure environment, you should not use an unmodified version of this application in production. Using this application in production risks unauthorized access to the encryption key or loss of the key needed to decrypt your data. The purpose of this tutorial is to demonstrate how to use Queryable Encryption without needing to set up a Key Management System.

You can use a Key Management System to securely store your encryption key in a production environment. A KMS is a remote service that securely stores and manages your encryption keys. To learn how to set up a Queryable Encryption enabled application that uses a KMS, see the Queryable Encryption Tutorials.

To complete and run the code in this guide, you need to set up your development environment as shown in the Install a Queryable Encryption Compatible Driver page.

Tip

See: Full Application

To see the complete code for this sample application, select the tab corresponding to your programming language and follow the provided link. Each sample application repository includes a README.md file that you can use to learn how to set up your environment and run the application.

Complete mongosh Application

1

The code samples in this tutorial use the following variables to perform the Queryable Encryption workflow:

  • kmsProviderName - The KMS you're using to store your Customer Master Key. Set this variable to "local" for this tutorial.

  • uri - Your MongoDB deployment connection URI. Set your connection URI in the MONGODB_URI environment variable or replace the value directly.

  • keyVaultDatabaseName - The database in MongoDB where your data encryption keys (DEKs) will be stored. Set this variable to "encryption".

  • keyVaultCollectionName - The collection in MongoDB where your DEKs will be stored. Set this variable to "__keyVault", which is the convention to help prevent mistaking it for a user collection.

  • keyVaultNamespace - The namespace in MongoDB where your DEKs will be stored. Set this variable to the values of the keyVaultDatabaseName and keyVaultCollectionName variables, separated by a period.

  • encryptedDatabaseName - The database in MongoDB where your encrypted data will be stored. Set this variable to "medicalRecords".

  • encryptedCollectionName - The collection in MongoDB where your encrypted data will be stored. Set this variable to "patients".

You can declare these variables by using the following code:

// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local"
const kmsProviderName = "<Your KMS Provider Name>";
const uri = process.env.MONGODB_URI; // Your connection URI
const keyVaultDatabaseName = "encryption";
const keyVaultCollectionName = "__keyVault";
const keyVaultNamespace = `${keyVaultDatabaseName}.${keyVaultCollectionName}`;
const encryptedDatabaseName = "medicalRecords";
const encryptedCollectionName = "patients";
  • kmsProviderName - The KMS you're using to store your Customer Master Key. Set this value to "local" for this tutorial.

  • keyVaultDatabaseName - The database in MongoDB where your data encryption keys (DEKs) will be stored. Set the value of keyVaultDatabaseName to "encryption".

  • keyVaultCollectionName - The collection in MongoDB where your DEKs will be stored. Set this variable to "__keyVault", which is the convention to help prevent mistaking it for a user collection.

  • keyVaultNamespace - The namespace in MongoDB where your DEKs will be stored. Set keyVaultNamespace to a new CollectionNamespace object whose name is the values of the keyVaultDatabaseName and keyVaultCollectionName variables, separated by a period.

  • encryptedDatabaseName - The database in MongoDB where your encrypted data will be stored. Set the value of encryptedDatabaseName to "medicalRecords".

  • encryptedCollectionName - The collection in MongoDB where your encrypted data will be stored. Set the value of encryptedCollectionName to "patients".

  • uri - Your MongoDB deployment connection URI. Set your connection URI in the appsettings.json file or replace the value directly.

You can declare these variables by using the following code:

// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local"
const string kmsProviderName = "<your KMS provider name>";
const string keyVaultDatabaseName = "encryption";
const string keyVaultCollectionName = "__keyVault";
var keyVaultNamespace =
CollectionNamespace.FromFullName($"{keyVaultDatabaseName}.{keyVaultCollectionName}");
const string encryptedDatabaseName = "medicalRecords";
const string encryptedCollectionName = "patients";
var appSettings = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
var uri = appSettings["MongoDbUri"];
  • kmsProviderName - The KMS you're using to store your Customer Master Key. Set this variable to "local" for this tutorial.

  • uri - Your MongoDB deployment connection URI. Set your connection URI in the MONGODB_URI environment variable or replace the value directly.

  • keyVaultDatabaseName - The database in MongoDB where your data encryption keys (DEKs) will be stored. Set this variable to "encryption".

  • keyVaultCollectionName - The collection in MongoDB where your DEKs will be stored. Set this variable to "__keyVault", which is the convention to help prevent mistaking it for a user collection.

  • keyVaultNamespace - The namespace in MongoDB where your DEKs will be stored. Set this variable to the values of the keyVaultDatabaseName and keyVaultCollectionName variables, separated by a period.

  • encryptedDatabaseName - The database in MongoDB where your encrypted data will be stored. Set this variable to "medicalRecords".

  • encryptedCollectionName - The collection in MongoDB where your encrypted data will be stored. Set this variable to "patients".

You can declare these variables by using the following code:

// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local"
kmsProviderName := "<KMS provider name>"
uri := os.Getenv("MONGODB_URI") // Your connection URI
keyVaultDatabaseName := "encryption"
keyVaultCollectionName := "__keyVault"
keyVaultNamespace := keyVaultDatabaseName + "." + keyVaultCollectionName
encryptedDatabaseName := "medicalRecords"
encryptedCollectionName := "patients"
  • kmsProviderName - The KMS you're using to store your Customer Master Key. Set this variable to "local" for this tutorial.

  • uri - Your MongoDB deployment connection URI. Set your connection URI in the MONGODB_URI environment variable or replace the value directly.

  • keyVaultDatabaseName - The database in MongoDB where your data encryption keys (DEKs) will be stored. Set this variable to "encryption".

  • keyVaultCollectionName - The collection in MongoDB where your DEKs will be stored. Set this variable to "__keyVault", which is the convention to help prevent mistaking it for a user collection.

  • keyVaultNamespace - The namespace in MongoDB where your DEKs will be stored. Set this variable to the values of the keyVaultDatabaseName and keyVaultCollectionName variables, separated by a period.

  • encryptedDatabaseName - The database in MongoDB where your encrypted data will be stored. Set this variable to "medicalRecords".

  • encryptedCollectionName - The collection in MongoDB where your encrypted data will be stored. Set this variable to "patients".

You can declare these variables by using the following code:

// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local"
String kmsProviderName = "<KMS provider name>";
String uri = QueryableEncryptionHelpers.getEnv("MONGODB_URI"); // Your connection URI
String keyVaultDatabaseName = "encryption";
String keyVaultCollectionName = "__keyVault";
String keyVaultNamespace = keyVaultDatabaseName + "." + keyVaultCollectionName;
String encryptedDatabaseName = "medicalRecords";
String encryptedCollectionName = "patients";
  • kmsProviderName - The KMS you're using to store your Customer Master Key. Set this variable to "local" for this tutorial.

  • uri - Your MongoDB deployment connection URI. Set your connection URI in the MONGODB_URI environment variable or replace the value directly.

  • keyVaultDatabaseName - The database in MongoDB where your data encryption keys (DEKs) will be stored. Set this variable to "encryption".

  • keyVaultCollectionName - The collection in MongoDB where your DEKs will be stored. Set this variable to "__keyVault", which is the convention to help prevent mistaking it for a user collection.

  • keyVaultNamespace - The namespace in MongoDB where your DEKs will be stored. Set this variable to the values of the keyVaultDatabaseName and keyVaultCollectionName variables, separated by a period.

  • encryptedDatabaseName - The database in MongoDB where your encrypted data will be stored. Set this variable to "medicalRecords".

  • encryptedCollectionName - The collection in MongoDB where your encrypted data will be stored. Set this variable to "patients".

You can declare these variables by using the following code:

// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local"
const kmsProviderName = "<Your KMS Provider Name>";
const uri = process.env.MONGODB_URI; // Your connection URI
const keyVaultDatabaseName = "encryption";
const keyVaultCollectionName = "__keyVault";
const keyVaultNamespace = `${keyVaultDatabaseName}.${keyVaultCollectionName}`;
const encryptedDatabaseName = "medicalRecords";
const encryptedCollectionName = "patients";
  • kms_provider_name - The KMS you're using to store your Customer Master Key. Set this variable to "local" for this tutorial.

  • uri - Your MongoDB deployment connection URI. Set your connection URI in the MONGODB_URI environment variable or replace the value directly.

  • key_vault_database_name - The database in MongoDB where your data encryption keys (DEKs) will be stored. Set this variable to "encryption".

  • key_vault_collection_name - The collection in MongoDB where your DEKs will be stored. Set this variable to "__keyVault", which is the convention to help prevent mistaking it for a user collection.

  • key_vault_namespace - The namespace in MongoDB where your DEKs will be stored. Set this variable to the values of the key_vault_database_name and key_vault_collection_name variables, separated by a period.

  • encrypted_database_name - The database in MongoDB where your encrypted data will be stored. Set this variable to "medicalRecords".

  • encrypted_collection_name - The collection in MongoDB where your encrypted data will be stored. Set this variable to "patients".

You can declare these variables by using the following code:

# KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local"
kms_provider_name = "<KMS provider name>"
uri = os.environ['MONGODB_URI'] # Your connection URI
key_vault_database_name = "encryption"
key_vault_collection_name = "__keyVault"
key_vault_namespace = f"{key_vault_database_name}.{key_vault_collection_name}"
encrypted_database_name = "medicalRecords"
encrypted_collection_name = "patients"

Important

Key Vault Collection Namespace Permissions

To complete this tutorial, the database user your application uses to connect to MongoDB must have dbAdmin permissions on the following namespaces:

  • encryption.__keyVault

  • medicalRecords database

Tip

Environment Variables

The sample code in this tutorial references environment variables that you need to set. Alternatively, you can replace the values directly in the code.

To learn how you can setup these environment variables, see the README.md file included in the sample application on GitHub.

Tip

Environment Variables

The sample code in this tutorial references environment variables that you need to set. Alternatively, you can replace the values directly in the code.

To learn how you can setup these environment variables, see the README.md file included in the sample application on GitHub.

Tip

Environment Variables

The sample code in this tutorial references environment variables that you need to set. Alternatively, you can replace the values directly in the code.

To learn how you can setup these environment variables, see the README.md file included in the sample application on GitHub.

Tip

Environment Variables

The sample code in this tutorial references environment variables that you need to set. Alternatively, you can replace the values directly in the code.

To learn how you can setup these environment variables, see the README.md file included in the sample application on GitHub.

Tip

Environment Variables

The sample code in this tutorial references environment variables that you need to set. Alternatively, you can replace the values directly in the code.

To learn how you can setup these environment variables, see the README.md file included in the sample application on GitHub.

Tip

Environment Variables

The sample code in this tutorial references environment variables that you need to set. Alternatively, you can replace the values directly in the code.

To learn how you can setup these environment variables, see the README.md file included in the sample application on GitHub.

2
1

You must create a Customer Master Key (CMK) to perform Queryable Encryption.

Create a 96-byte Customer Master Key and save it to your filesystem as the file customer-master-key.txt:

customerMasterKeyPath = "customer-master-key.txt";
if (!fs.existsSync(customerMasterKeyPath)) {
fs.writeFileSync(customerMasterKeyPath, crypto.randomBytes(96));
}
using var randomNumberGenerator = RandomNumberGenerator.Create();
try
{
var bytes = new byte[96];
randomNumberGenerator.GetBytes(bytes);
var localCustomerMasterKeyBase64 = Convert.ToBase64String(bytes);
File.WriteAllText("customer-master-key.txt", localCustomerMasterKeyBase64);
}
catch (Exception e)
{
throw new Exception("Unable to write Customer Master Key file due to the following error: " + e.Message);
}
key := make([]byte, 96)
if _, err := rand.Read(key); err != nil {
panic(fmt.Sprintf("Unable to create a random 96 byte data key: %v\n", err))
}
if err := os.WriteFile("customer-master-key.txt", key, 0644); err != nil {
panic(fmt.Sprintf("Unable to write key to file: %v\n", err))
}
byte[] localCustomerMasterKey = new byte[96];
new SecureRandom().nextBytes(localCustomerMasterKey);
try (FileOutputStream stream = new FileOutputStream("customer-master-key.txt")) {
stream.write(localCustomerMasterKey);
// ...
if (!existsSync("./customer-master-key.txt")) {
try {
writeFileSync("customer-master-key.txt", randomBytes(96));
} catch (err) {
throw new Error(
`Unable to write Customer Master Key to file due to the following error: ${err}`
);
}
}
path = "customer-master-key.txt"
file_bytes = os.urandom(96)
with open(path, "wb") as f:
f.write(file_bytes)

Warning

Do Not Use a Local Key File in Production

A local key file in your filesystem is insecure and is not recommended for production. Instead, you should store your Customer Master Keys in a remote Key Management System (KMS).

To learn how to use a remote KMS in your Queryable Encryption implementation, see the Tutorials guide.

Tip

Generate a CMK from the Command Line

Use the following command to generate a CMK from a Unix shell or PowerShell:

  • Unix shell:

    echo $(head -c 96 /dev/urandom | base64 | tr -d '\n')
  • PowerShell:

    $r=[byte[]]::new(64);$g=[System.Security.Cryptography.RandomNumberGenerator]::Create();$g.GetBytes($r);[Convert]::ToBase64String($r)

Save the output of the preceding command to a file named customer-master-key.txt.

2

Retrieve the contents of the Customer Master Key file that you generated in the Create a Customer Master Key step of this guide.

Pass the CMK value to your KMS provider settings. The client uses these settings to discover the CMK. Set the provider name to local to inform the driver you are using a Local Key Provider.

// WARNING: Do not use a local key file in a production application
const localMasterKey = fs.readFileSync("./customer-master-key.txt");
if (localMasterKey.length !== 96) {
throw new Error(
"Expected the customer master key file to be 96 bytes."
);
}
kmsProviderCredentials = {
local: {
key: localMasterKey,
},
};
// WARNING: Do not use a local key file in a production application
var kmsProviderCredentials = new Dictionary<string, IReadOnlyDictionary<string, object>>();
try
{
var localCustomerMasterKeyBase64 = File.ReadAllText("customer-master-key.txt");
var localCustomerMasterKeyBytes = Convert.FromBase64String(localCustomerMasterKeyBase64);
if (localCustomerMasterKeyBytes.Length != 96)
{
throw new Exception("Expected the customer master key file to be 96 bytes.");
}
var localOptions = new Dictionary<string, object>
{
{ "key", localCustomerMasterKeyBytes }
};
kmsProviderCredentials.Add("local", localOptions);
}
key, err := os.ReadFile("customer-master-key.txt")
if err != nil {
panic(fmt.Sprintf("Could not read the Customer Master Key: %v", err))
}
if len(key) != 96 {
panic(fmt.Sprintf("Expected the customer master key file to be 96 bytes."))
}
kmsProviderCredentials := map[string]map[string]interface{}{"local": {"key": key}}
byte[] localCustomerMasterKey = new byte[96];
try (FileInputStream fis = new FileInputStream("customer-master-key.txt")) {
if (fis.read(localCustomerMasterKey) != 96)
throw new Exception("Expected the customer master key file to be 96 bytes.");
} catch (Exception e) {
throw new Exception("Unable to read the Customer Master Key due to the following error: " + e.getMessage());
}
Map<String, Object> keyMap = new HashMap<String, Object>();
keyMap.put("key", localCustomerMasterKey);
Map<String, Map<String, Object>> kmsProviderCredentials = new HashMap<String, Map<String, Object>>();
kmsProviderCredentials.put("local", keyMap);
// WARNING: Do not use a local key file in a production application
const localMasterKey = readFileSync("./customer-master-key.txt");
if (localMasterKey.length !== 96) {
throw new Error(
"Expected the customer master key file to be 96 bytes."
);
}
kmsProviders = {
local: {
key: localMasterKey,
},
};
path = "./customer-master-key.txt"
with open(path, "rb") as f:
local_master_key = f.read()
if len(local_master_key) != 96:
raise Exception("Expected the customer master key file to be 96 bytes.")
kms_provider_credentials = {
"local": {
"key": local_master_key
},
}
3

Create an autoEncryptionOptions object that contains the following options:

  • The namespace of your Key Vault collection

  • The kmsProviderCredentials object, defined in the previous step

const autoEncryptionOptions = {
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviderCredentials,
};

Create an AutoEncryptionOptions object that contains the following options:

  • The namespace of your Key Vault collection

  • The kmsProviderCredentials object, defined in the previous step

  • The extraOptions object, which contains the path to your Automatic Encryption Shared Library

var extraOptions = new Dictionary<string, object>
{
{ "cryptSharedLibPath", _appSettings["CryptSharedLibPath"] } // Path to your Automatic Encryption Shared Library
};
var autoEncryptionOptions = new AutoEncryptionOptions(
keyVaultNamespace,
kmsProviderCredentials,
extraOptions: extraOptions);

Create an AutoEncryption object that contains the following options:

  • The namespace of your Key Vault collection

  • The kmsProviderCredentials object, defined in the previous step

  • The cryptSharedLibraryPath object, which contains the path to your Automatic Encryption Shared Library

cryptSharedLibraryPath := map[string]interface{}{
"cryptSharedLibPath": os.Getenv("SHARED_LIB_PATH"), // Path to your Automatic Encryption Shared Library
}
autoEncryptionOptions := options.AutoEncryption().
SetKeyVaultNamespace(keyVaultNamespace).
SetKmsProviders(kmsProviderCredentials).
SetExtraOptions(cryptSharedLibraryPath)

Create an AutoEncryptionSettings object that contains the following options:

  • The namespace of your Key Vault collection

  • The kmsProviderCredentials object, defined in the previous step

  • The extraOptions object, which contains the path to your Automatic Encryption Shared Library

Map<String, Object> extraOptions = new HashMap<String, Object>();
extraOptions.put("cryptSharedLibPath", getEnv("SHARED_LIB_PATH")); // Path to your Automatic Encryption Shared Library
AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder()
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviderCredentials)
.extraOptions(extraOptions)
.build();

Create an autoEncryptionOptions object that contains the following options:

  • The namespace of your Key Vault collection

  • The kmsProviders object, defined in the previous step

  • The sharedLibraryPathOptions object, which contains the path to your Automatic Encryption Shared Library

const extraOptions = {
cryptSharedLibPath: process.env.SHARED_LIB_PATH, // Path to your Automatic Encryption Shared Library
};
const autoEncryptionOptions = {
keyVaultNamespace,
kmsProviders,
extraOptions,
};

Create an AutoEncryptionOpts object that contains the following options:

  • The kms_provider_credentials object, defined in the previous step

  • The namespace of your Key Vault collection

  • The path to your Automatic Encryption Shared Library

auto_encryption_options = AutoEncryptionOpts(
kms_provider_credentials,
key_vault_namespace,
crypt_shared_lib_path=os.environ['SHARED_LIB_PATH'] # Path to your Automatic Encryption Shared Library>
)

Note

Automatic Encryption Options

The automatic encryption options provide configuration information to the Automatic Encryption Shared Library, which modifies the application's behavior when accessing encrypted fields.

To learn more about the Automatic Encryption Shared Library, see the Automatic Encryption Shared Library page.

4

To create a client used to encrypt and decrypt data in your collection, instantiate a new MongoClient by using your connection URI and your automatic encryption options.

const encryptedClient = Mongo(uri, autoEncryptionOpts);
var clientSettings = MongoClientSettings.FromConnectionString(uri);
clientSettings.AutoEncryptionOptions = qeHelpers.GetAutoEncryptionOptions(
keyVaultNamespace,
kmsProviderCredentials);
var encryptedClient = new MongoClient(clientSettings);
encryptedClient, err := mongo.Connect(
context.TODO(),
options.Client().ApplyURI(uri).SetAutoEncryptionOptions(autoEncryptionOptions),
)
if err != nil {
panic(fmt.Sprintf("Unable to connect to MongoDB: %v\n", err))
}
defer func() {
_ = encryptedClient.Disconnect(context.TODO())
}()
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(uri))
.autoEncryptionSettings(autoEncryptionSettings)
.build();
try (MongoClient encryptedClient = MongoClients.create(clientSettings)) {
const encryptedClient = new MongoClient(uri, {
autoEncryption: autoEncryptionOptions,
});
encrypted_client = MongoClient(
uri, auto_encryption_opts=auto_encryption_options)
5

To encrypt a field, add it to the encryption schema. To enable queries on a field, add the "queries" property. Create the encryption schema as follows:

const encryptedFieldsMap = {
encryptedFields: {
fields: [
{
path: "patientRecord.ssn",
bsonType: "string",
queries: { queryType: "equality" },
},
{
path: "patientRecord.billing",
bsonType: "object",
},
],
},
};
var encryptedFields = new BsonDocument
{
{
"fields", new BsonArray
{
new BsonDocument
{
{ "keyId", BsonNull.Value },
{ "path", "patientRecord.ssn" },
{ "bsonType", "string" },
{ "queries", new BsonDocument("queryType", "equality") }
},
new BsonDocument
{
{ "keyId", BsonNull.Value },
{ "path", "patientRecord.billing" },
{ "bsonType", "object" }
}
}
}
};
encryptedFieldsMap := bson.M{
"fields": []bson.M{
bson.M{
"keyId": nil,
"path": "patientRecord.ssn",
"bsonType": "string",
"queries": []bson.M{
{
"queryType": "equality",
},
},
},
bson.M{
"keyId": nil,
"path": "patientRecord.billing",
"bsonType": "object",
},
},
}
BsonDocument encryptedFieldsMap = new BsonDocument().append("fields",
new BsonArray(Arrays.asList(
new BsonDocument()
.append("keyId", new BsonNull())
.append("path", new BsonString("patientRecord.ssn"))
.append("bsonType", new BsonString("string"))
.append("queries", new BsonDocument()
.append("queryType", new BsonString("equality"))),
new BsonDocument()
.append("keyId", new BsonNull())
.append("path", new BsonString("patientRecord.billing"))
.append("bsonType", new BsonString("object")))));
const encryptedFieldsMap = {
encryptedFields: {
fields: [
{
path: "patientRecord.ssn",
bsonType: "string",
queries: { queryType: "equality" },
},
{
path: "patientRecord.billing",
bsonType: "object",
},
],
},
};
encrypted_fields_map = {
"fields": [
{
"path": "patientRecord.ssn",
"bsonType": "string",
"queries": [{"queryType": "equality"}]
},
{
"path": "patientRecord.billing",
"bsonType": "object",
}
]
}

Note

In the previous code sample, both the "ssn" and "billing" fields are encrypted, but only the "ssn" field can be queried.

6

Instantiate ClientEncryption to access the API for the encryption helper methods.

const clientEncryption = encryptedClient.getClientEncryption()
var clientEncryptionOptions = new ClientEncryptionOptions(
keyVaultClient: keyVaultClient,
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviderCredentials
);
var clientEncryption = new ClientEncryption(clientEncryptionOptions);
opts := options.ClientEncryption().
SetKeyVaultNamespace(keyVaultNamespace).
SetKmsProviders(kmsProviderCredentials)
clientEncryption, err := mongo.NewClientEncryption(encryptedClient, opts)
if err != nil {
panic(fmt.Sprintf("Unable to create a ClientEncryption instance due to the following error: %s\n", err))
}
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(uri))
.build())
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviderCredentials)
.build();
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
const clientEncryption = new ClientEncryption(
encryptedClient,
autoEncryptionOptions
);
client_encryption = ClientEncryption(
kms_providers=kms_provider_credentials,
key_vault_namespace=key_vault_namespace,
key_vault_client=encrypted_client,
codec_options=CodecOptions(uuid_representation=STANDARD)
)

Because you are using a local Customer Master Key, you don't need to provide Customer Master Key credentials. Create a variable containing an empty object to use in place of credentials when you create your encrypted collection.

customerMasterKeyCredentials = {};
var customerMasterKeyCredentials = new BsonDocument();
cmkCredentials := map[string]string{}
BsonDocument customerMasterKeyCredentials = new BsonDocument();
customerMasterKeyCredentials = {};
customer_master_key_credentials = {}

Create your encrypted collection by using the encryption helper method accessed through the ClientEncryption class. This method automatically generates data encryption keys for your encrypted fields and creates the encrypted collection:

await clientEncryption.createEncryptedCollection(
encryptedDatabaseName,
encryptedCollectionName,
{
provider: kmsProviderName,
createCollectionOptions: encryptedFieldsMap,
masterKey: customerMasterKeyCredentials,
}
);

The C# version of this tutorial uses separate classes as data models to represent the document structure. Add the following Patient, PatientRecord, and PatientBilling classes to your project:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
[BsonIgnoreExtraElements]
public class Patient
{
public ObjectId Id { get; set; }
public string PatientName { get; set; }
public PatientRecord PatientRecord { get; set; }
}
public class PatientRecord
{
public string Ssn { get; set; }
public PatientBilling Billing { get; set; }
}
public class PatientBilling
{
public string CardType { get; set; }
public long CardNumber { get; set; }
}

After you've added these classes, create your encrypted collection by using the encryption helper method accessed through the ClientEncryption class. This method automatically generates data encryption keys for your encrypted fields and creates the encrypted collection:

var createCollectionOptions = new CreateCollectionOptions<Patient>
{
EncryptedFields = encryptedFields
};
clientEncryption.CreateEncryptedCollection(patientDatabase,
encryptedCollectionName,
createCollectionOptions,
kmsProviderName,
customerMasterKeyCredentials);

Tip

Database vs. Database Name

The method that creates the encrypted collection requires a reference to a database object rather than the database name. You can obtain this reference by using a method on your client object.

The Golang version of this tutorial uses data models to represent the document structure. Add the following structs to your project to represent the data in your collection:

type PatientDocument struct {
PatientName string `bson:"patientName"`
PatientID int32 `bson:"patientId"`
PatientRecord PatientRecord `bson:"patientRecord"`
}
type PatientRecord struct {
SSN string `bson:"ssn"`
Billing PaymentInfo `bson:"billing"`
}
type PaymentInfo struct {
Type string `bson:"type"`
Number string `bson:"number"`
}

After you've added these classes, create your encrypted collection by using the encryption helper method accessed through the ClientEncryption class. This method automatically generates data encryption keys for your encrypted fields and creates the encrypted collection:

createCollectionOptions := options.CreateCollection().SetEncryptedFields(encryptedFieldsMap)
_, _, err =
clientEncryption.CreateEncryptedCollection(
context.TODO(),
encryptedClient.Database(encryptedDatabaseName),
encryptedCollectionName,
createCollectionOptions,
kmsProviderName,
customerMasterKey,
)

Tip

Database vs. Database Name

The method that creates the encrypted collection requires a reference to a database object rather than the database name. You can obtain this reference by using a method on your client object.

Create your encrypted collection by using the encryption helper method accessed through the ClientEncryption class. This method automatically generates data encryption keys for your encrypted fields and creates the encrypted collection:

CreateCollectionOptions createCollectionOptions = new CreateCollectionOptions().encryptedFields(encryptedFieldsMap);
CreateEncryptedCollectionParams encryptedCollectionParams = new CreateEncryptedCollectionParams(kmsProviderName);
encryptedCollectionParams.masterKey(customerMasterKeyCredentials);
try {
clientEncryption.createEncryptedCollection(
encryptedClient.getDatabase(encryptedDatabaseName),
encryptedCollectionName,
createCollectionOptions,
encryptedCollectionParams);
}

Tip

Database vs. Database Name

The method that creates the encrypted collection requires a reference to a database object rather than the database name. You can obtain this reference by using a method on your client object.

Create your encrypted collection by using the encryption helper method accessed through the ClientEncryption class. This method automatically generates data encryption keys for your encrypted fields and creates the encrypted collection:

Note

Import ClientEncryption

When using the Node.js driver v6.0 and later, you must import ClientEncryption from mongodb.

For earlier driver versions, import ClientEncryption from mongodb-client-encryption.

await clientEncryption.createEncryptedCollection(
encryptedDatabase,
encryptedCollectionName,
{
provider: kmsProviderName,
createCollectionOptions: encryptedFieldsMap,
masterKey: customerMasterKeyCredentials,
}
);

Tip

Database vs. Database Name

The method that creates the encrypted collection requires a reference to a database object rather than the database name. You can obtain this reference by using a method on your client object.

Create your encrypted collection by using the encryption helper method accessed through the ClientEncryption class. This method automatically generates data encryption keys for your encrypted fields and creates the encrypted collection:

client_encryption.create_encrypted_collection(
encrypted_client[encrypted_database_name],
encrypted_collection_name,
encrypted_fields_map,
kms_provider_name,
customer_master_key_credentials,
)

Tip

Database vs. Database Name

The method that creates the encrypted collection requires a reference to a database object rather than the database name. You can obtain this reference by using a method on your client object.

3

Create a sample document that describes a patient's personal information. Use the encrypted client to insert it into the patients collection, as shown in the following example:

const patientDocument = {
patientName: "Jon Doe",
patientId: 12345678,
patientRecord: {
ssn: "987-65-4320",
billing: {
type: "Visa",
number: "4111111111111111",
},
},
};
const encryptedCollection = encryptedClient.getDB(encryptedDatabaseName).getCollection(encryptedCollectionName);
const insertResult = await encryptedCollection.insertOne(patientDocument);

Create a sample document that describes a patient's personal information. Use the encrypted client to insert it into the patients collection, as shown in the following example:

var patient = new Patient
{
PatientName = "Jon Doe",
Id = new ObjectId(),
PatientRecord = new PatientRecord
{
Ssn = "987-65-4320",
Billing = new PatientBilling
{
CardType = "Visa",
CardNumber = 4111111111111111
}
}
};
var encryptedCollection = encryptedClient.GetDatabase(encryptedDatabaseName).
GetCollection<Patient>(encryptedCollectionName);
encryptedCollection.InsertOne(patient);

Create a sample document that describes a patient's personal information. Use the encrypted client to insert it into the patients collection, as shown in the following example:

patientDocument := &PatientDocument{
PatientName: "Jon Doe",
PatientID: 12345678,
PatientRecord: PatientRecord{
SSN: "987-65-4320",
Billing: PaymentInfo{
Type: "Visa",
Number: "4111111111111111",
},
},
}
coll := encryptedClient.Database(encryptedDatabaseName).Collection(encryptedCollectionName)
_, err = coll.InsertOne(context.TODO(), patientDocument)
if err != nil {
panic(fmt.Sprintf("Unable to insert the patientDocument: %s", err))
}

This tutorial uses POJOs as data models to represent the document structure. To set up your application to use POJOs, add the following code:

CodecProvider pojoCodecProvider = PojoCodecProvider.builder().automatic(true).build();
CodecRegistry pojoCodecRegistry = fromRegistries(getDefaultCodecRegistry(), fromProviders(pojoCodecProvider));

To learn more about Java POJOs, see the Plain Old Java Object wikipedia article.

This tutorial uses the following POJOs:

  • Patient

  • PatientRecord

  • PatientBilling

You can view these classes in the models package of the complete Java application.

Add these POJO classes to your application. Then, create an instance of a Patient that describes a patient's personal information. Use the encrypted client to insert it into the patients collection, as shown in the following example:

MongoDatabase encryptedDb = encryptedClient.getDatabase(encryptedDatabaseName).withCodecRegistry(pojoCodecRegistry);
MongoCollection<Patient> collection = encryptedDb.getCollection(encryptedCollectionName, Patient.class);
PatientBilling patientBilling = new PatientBilling("Visa", "4111111111111111");
PatientRecord patientRecord = new PatientRecord("987-65-4320", patientBilling);
Patient patientDocument = new Patient("Jon Doe", patientRecord);
InsertOneResult result = collection.insertOne(patientDocument);

Create a sample document that describes a patient's personal information. Use the encrypted client to insert it into the patients collection, as shown in the following example:

const patientDocument = {
patientName: "Jon Doe",
patientId: 12345678,
patientRecord: {
ssn: "987-65-4320",
billing: {
type: "Visa",
number: "4111111111111111",
},
},
};
const encryptedCollection = encryptedClient
.db(encryptedDatabaseName)
.collection(encryptedCollectionName);
const result = await encryptedCollection.insertOne(patientDocument);

Create a sample document that describes a patient's personal information. Use the encrypted client to insert it into the patients collection, as shown in the following example:

patient_document = {
"patientName": "Jon Doe",
"patientId": 12345678,
"patientRecord": {
"ssn": "987-65-4320",
"billing": {
"type": "Visa",
"number": "4111111111111111",
},
},
}
encrypted_collection = encrypted_client[encrypted_database_name][encrypted_collection_name]
result = encrypted_collection.insert_one(patient_document)
4

The following code sample executes a find query on an encrypted field and prints the decrypted data:

const findResult = await encryptedCollection.findOne({
"patientRecord.ssn": "987-65-4320",
});
console.log(findResult);
var ssnFilter = Builders<Patient>.Filter.Eq("patientRecord.ssn", patient.PatientRecord.Ssn);
var findResult = await encryptedCollection.Find(ssnFilter).ToCursorAsync();
Console.WriteLine(findResult.FirstOrDefault().ToJson());
var findResult PatientDocument
err = coll.FindOne(
context.TODO(),
bson.M{"patientRecord.ssn": "987-65-4320"},
).Decode(&findResult)
Patient findResult = collection.find(
new BsonDocument()
.append("patientRecord.ssn", new BsonString("987-65-4320")))
.first();
System.out.println(findResult);
const findResult = await encryptedCollection.findOne({
"patientRecord.ssn": "987-65-4320",
});
console.log(findResult);
find_result = encrypted_collection.find_one({
"patientRecord.ssn": "987-65-4320"
})
print(find_result)

The output of the preceding code sample should look similar to the following:

{
"_id": {
"$oid": "648b384a722cb9b8392df76a"
},
"name": "Jon Doe",
"record": {
"ssn": "987-65-4320",
"billing": {
"type": "Visa",
"number": "4111111111111111"
}
},
"__safeContent__": [
{
"$binary": {
"base64": "L1NsYItk0Sg+oL66DBj6IYHbX7tveANQyrU2cvMzD9Y=",
"subType": "00"
}
}
]
}

Warning

Do not Modify the __safeContent__ Field

The __safeContent__ field is essential to Queryable Encryption. Do not modify the contents of this field.

To view a tutorial on production-ready Queryable Encryption with a remote KMS, see Tutorials.

To learn how Queryable Encryption works, see Fundamentals.

To learn more about the topics mentioned in this guide, see the following links:

  • Learn more about Queryable Encryption components on the Reference page.

  • Learn how Customer Master Keys and Data Encryption Keys work on the Encryption Keys and Key Vaults page.

  • See how KMS Providers manage your Queryable Encryption keys on the KMS Providers page.

Back

Features

Next

Fundamentals