Docs HomeMongoDB Manual

Use Explicit Encryption使用显式加密

Queryable Encryption with equality queries is generally available (GA) in MongoDB 7.0 and later. 具有相等查询的可查询加密在MongoDB 7.0及更高版本中通常可用(GA)。The Queryable Encryption Public Preview, released in version 6.0, is no longer supported. Data encrypted using the Public Preview is incompatible with the feature release. 不再支持6.0版本中发布的“可查询加密预览”。使用公共预览加密的数据与功能版本不兼容。For more information, see Compatibility Changes in MongoDB 7.0.有关更多信息,请参阅MongoDB 7.0中的兼容性更改

Overview概述

This guide shows you how to encrypt a document with explicit encryption and a MongoDB driver.本指南向您展示如何使用显式加密和MongoDB驱动程序加密文档。

After completing this guide, you should be able to configure a driver to encrypt fields in a document using explicit encryption. With this knowledge, you should be able to create a client application that uses explicit encryption. with automatic decryption.完成本指南后,您应该能够配置驱动程序,以便使用显式加密来加密文档中的字段。有了这些知识,您应该能够创建一个使用显式加密的客户端应用程序。具有自动解密功能。

Important

Do Not Use this Application In Production请勿在生产中使用此应用程序

Since this example application stores an encryption key on your application's filesystem, you risk unauthorized access to the key or loss of the key to decrypt your data.由于此示例应用程序将加密键存储在应用程序的文件系统上,因此您可能会面临未经授权访问键或丢失解密数据的键的风险。

To view a tutorial that demonstrates how to create a Queryable Encryption enabled application that uses a remote Key Management System, see Tutorials.要查看演示如何创建使用远程键管理系统的启用可查询加密的应用程序的教程,请参阅教程

Before You Get Started开始之前

To complete and run the code in this guide, you need to set up your development environment as shown in the Installation Requirements page.要完成并运行本指南中的代码,您需要设置开发环境,如安装要求页面中所示。

Tip

See: Full Application请参阅:完整应用程序

To see the complete code for the application you make in this guide, select the tab corresponding to your preferred MongoDB driver and follow the provided link:要在本指南中查看您制作的应用程序的完整代码,请选择与您首选的MongoDB驱动程序相对应的选项卡,然后单击提供的链接:

Procedure过程

1

Create a Customer Master Key创建客户主键

You must create a Customer Master Key (CMK) to perform Queryable Encryption.必须创建客户主键(CMK)才能执行可查询加密。

Create a 96-byte Customer Master Key and save it to the file master-key.txt:创建一个96字节的客户主键,并将其保存到master-key.txt文件中:

const fs = require("fs");
const crypto = require("crypto");
try {
fs.writeFileSync("master-key.txt", crypto.randomBytes(96));
} catch (err) {
console.error(err);
}
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).文件系统中的本地键文件是不安全的,不建议用于生产。相反,您应该将客户主键存储在远程键管理系统(KMS)中。

To learn how to use a remote KMS in your Queryable Encryption implementation, see the Tutorials guide.要了解如何在可查询加密实现中使用远程KMS,请参阅教程指南。

Tip

Generate a CMK from the Command Line从命令行生成CMK

Use the following command to generate a CMK from a Unix shell or PowerShell:使用以下命令从Unix shell或PowerShell生成CMK

  • 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 master-key.txt.将前面命令的输出保存到名为master-key.txt的文件中。

Tip

See: Complete Code

To view the complete code for making a Customer Master Key, see the Queryable Encryption sample application repository.要查看制作客户主键的完整代码,请参阅可查询加密示例应用程序存储库

2

Create a Unique Index on your Key Vault collection在键库集合上创建唯一索引

Create a unique index on the keyAltNames field in your encryption.__keyVault namespace.encryption.__keyVault命名空间中的keyAltNames字段上创建一个唯一索引。

Select the tab corresponding to your preferred MongoDB driver:选择与您首选的MongoDB驱动程序相对应的选项卡:

const uri = "<Your Connection String>";
const keyVaultClient = new MongoClient(uri);
await keyVaultClient.connect();
const keyVaultDB = keyVaultClient.db(keyVaultDatabase);
// Drop the Key Vault Collection in case you created this collection in a previous run of this application.如果您在以前运行此应用程序时创建了键保管库集合,请删除该集合。
await keyVaultDB.dropDatabase();
const keyVaultColl = keyVaultDB.collection(keyVaultCollection);
await keyVaultColl.createIndex(
{ keyAltNames: 1 },
{
unique: true,
partialFilterExpression: { keyAltNames: { $exists: true } },
}
);
3

Create your Data Encryption Keys and Encrypted Collection创建数据加密键和加密集合

1

Read the Customer Master Key and Specify KMS Provider Settings读取客户主键并指定KMS提供程序设置

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. CMK值传递给您的KMS提供程序设置。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.客户端使用这些设置来发现CMK。将提供程序名称设置为本地,以通知驱动程序您正在使用本地键提供程序。

Select the tab corresponding to your preferred MongoDB driver:选择与您首选的MongoDB驱动程序相对应的选项卡:

const provider = "local";
const path = "./master-key.txt";
// WARNING: Do not use a local key file in a production application警告:请勿在生产应用程序中使用本地键文件
const localMasterKey = fs.readFileSync(path);
const kmsProviders = {
local: {
key: localMasterKey,
},
};
2

Create your Data Encryption Keys创建数据加密键

Construct a client with your MongoDB connection string and Key Vault collection namespace, and create the Data Encryption Keys:使用MongoDB连接字符串和键库集合命名空间构建客户端,并创建数据加密键:

Note

Key Vault Collection Namespace Permissions键保管库集合命名空间权限

The Key Vault collection is in the encryption.__keyVault namespace. 键保管库集合处于encryption.__keyVault命名空间。Ensure that the database user your application uses to connect to MongoDB has ReadWrite permissions on this namespace.确保应用程序用于连接MongoDB的数据库用户对此命名空间具有ReadWrite权限。

const clientEnc = new ClientEncryption(keyVaultClient, {
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders,
});
const dek1 = await clientEnc.createDataKey(provider, {
keyAltNames: ["dataKey1"],
});
const dek2 = await clientEnc.createDataKey(provider, {
keyAltNames: ["dataKey2"],
});
3

Create Your Encrypted Collection创建加密集合

Use a Queryable Encryption enabled MongoClient instance to specify what fields you must encrypt and create your encrypted collection:使用启用可查询加密的MongoClient实例指定必须加密的字段并创建加密的集合:

const encryptedFieldsMap = {
[`${secretDB}.${secretCollection}`]: {
fields: [
{
keyId: dek1,
path: "patientId",
bsonType: "int",
queries: { queryType: "equality" },
},
{
keyId: dek2,
path: "medications",
bsonType: "array",
},
],
},
};
const extraOptions = {
cryptSharedLibPath: "<path to FLE Shared Library>",
};
const encClient = new MongoClient(uri, {
autoEncryption: {
keyVaultNamespace,
kmsProviders,
extraOptions,
encryptedFieldsMap,
},
});
await encClient.connect();
const newEncDB = encClient.db(secretDB);
// Drop the encrypted collection in case you created this collection in a previous run of this application.如果您在以前运行此应用程序时创建了此集合,请删除加密的集合。
await newEncDB.dropDatabase();
await newEncDB.createCollection(secretCollection);
console.log("Created encrypted collection!");

The output from the code in this section should resemble the following:本节中代码的输出应类似于以下内容:

Created encrypted collection!
Tip

See: Complete Code请参阅:完整代码

To view the complete code for making a Data Encryption Key, see the Queryable Encryption sample application repository.要查看制作数据加密键的完整代码,请参阅可查询加密示例应用程序存储库

4

Configure your MongoClient for Encrypted Reads and Writes为加密读取和写入配置MongoClient

1

Specify the Key Vault Collection Namespace指定键保管库集合命名空间

Specify encryption.__keyVault as the Key Vault collection namespace.指定encryption.__keyVault作为Key Vault集合命名空间。

const eDB = "encryption";
const eKV = "__keyVault";
const keyVaultNamespace = `${eDB}.${eKV}`;
const secretDB = "medicalRecords";
const secretCollection = "patients";
2

Specify the Customer Master Key指定客户主键

Specify the KMS provider and specify your Customer Master Key inline:指定KMS提供程序并内联指定您的客户主键:

const fs = require("fs");
const path = "./master-key.txt";
// WARNING: Do not use a local key file in a production application
const localMasterKey = fs.readFileSync(path);
const kmsProviders = {
local: {
key: localMasterKey,
},
};
3

Retrieve Data Encryption Keys检索数据加密键

Retrieve the Data Encryption Keys created in the Create a Data Encryption Key step of this guide:检索在本指南的创建数据加密键步骤中创建的数据加密键

const uri = "<Your MongoDB URI>";
const unencryptedClient = new MongoClient(uri);
await unencryptedClient.connect();
const keyVaultClient = unencryptedClient.db(eDB).collection(eKV);
const dek1 = await keyVaultClient.findOne({ keyAltNames: "dataKey1" });
const dek2 = await keyVaultClient.findOne({ keyAltNames: "dataKey2" });
4

Specify the Path of the Automatic Encryption Shared Library指定自动加密共享库的路径

const extraOptions = {
cryptSharedLibPath: "<path to crypt_shared library>",
};
Tip

Learn More了解更多信息

To learn more about the library referenced by this path, see the Automatic Encryption Shared Library for Queryable Encryption page.要了解有关此路径引用的库的更多信息,请参阅可查询加密的自动加密共享库页面。

5

Create a MongoClient Object创建MongoClient对象

Instantiate a MongoClient object with the following automatic encryption settings:使用以下自动加密设置实例化MongoClient对象:

const encryptedClient = new MongoClient(uri, {
autoEncryption: {
kmsProviders: kmsProviders,
keyVaultNamespace: keyVaultNamespace,
bypassQueryAnalysis: true,
keyVaultClient: unencryptedClient,
extraOptions: extraOptions,
},
});
await encryptedClient.connect();
Note

Automatic Decryption自动解密

We use a MongoClient instance with automatic encryption enabled to perform automatic decryption.我们使用启用了自动加密的MongoClient实例来执行自动解密。

To learn more about explicit encryption with automatic decryption, see the Fundamentals section.要了解有关使用自动解密的显式加密的更多信息,请参阅基础知识部分。

6

Create a ClientEncryption Object创建ClientEncryption对象

Instantiate a ClientEncryption object as follows:实例化ClientEncryption对象,如下所示:

const encryption = new ClientEncryption(unencryptedClient, {
keyVaultNamespace,
kmsProviders,
});
5

Insert a Document with Encrypted Fields插入带有加密字段的文档

Use your Queryable Encryption enabled MongoClient instance to insert a document with encrypted fields into the medicalRecords.patients namespace using the following code snippet:使用启用可查询加密的MongoClient实例,使用以下代码片段将具有加密字段的文档插入medicalRecords.patients命名空间:

const patientId = 12345678;
const medications = ["Atorvastatin", "Levothyroxine"];

const indexedInsertPayload = await encryption.encrypt(patientId, {
algorithm: "Indexed",
keyId: dek1._id,
contentionFactor: 1,
});
const unindexedInsertPayload = await encryption.encrypt(medications, {
algorithm: "Unindexed",
keyId: dek2._id,
});
const encryptedColl = encryptedClient
.db(secretDB)
.collection(secretCollection);
await encryptedColl.insertOne({
firstName: "Jon",
patientId: indexedInsertPayload,
medications: unindexedInsertPayload,
});

When you insert a document, your Queryable Encryption enabled client encrypts the fields of your document such that it resembles the following:插入文档时,启用可查询加密的客户端会对文档的字段进行加密,使其类似于以下内容:

{
"_id": {
"$oid": "6303e36053cc7ec2e6a630bd"
},
"firstName": "Jon",
"patientId": {
"$binary": {
"base64": "BxLJUBmg703civqMz8ASsD4QEYeSneOGiiYHfLE77ELEkp1EC/fXPrKCNRQl2mAFddszqDJ0P3znKrq0DVMEvJoU6wa0Ra+U+JjNVr8NtJE+TpTLCannY5Av6iGfLAaiHbM/E8Ftz1YCQsArQwuNp3wIV/GJPLa2662xsyk0wz7F6IRGC3FlnxpN4UIFaHE1M7Y6kEnx3tEy5uJBvU4Sex7I2H0kqHthClH77Q6xHIHc8H9d6upvgnEbkKBCnmc24A2pSG/xZ7LBsV3j5aOboPISuN/lvg==",
"subType": "06"
}
},
"medications": {
"$binary": {
"base64": "BvOsveapfUxiuQxCMSM2fYIEyRlQaSqR+0NxlMarwurBflvoMz1FrSjSGgCVCpK8X+YrilP6Bac99kkaUmRJfjo4savxcjpOfEnUj5bHciPyfQBYmYF4PMLDtTTzGZpPilb9d5KgpIMBXxHi+dIcog==",
"subType": "06"
}
},
"__safeContent__": [
{
"$binary": {
"base64": "ZLPIpgxzXpHUGrvdIHetwmMagR+mqvuUj5nzXNGf/WM=",
"subType": "00"
}
}
]
}
Warning

Do not Modify the __safeContent__ Field不要修改__safeContent__字段

The __safeContent__ field is essential to Queryable Encryption. Do not modify the contents of this field.__safeContent__字段对于可查询加密至关重要。请勿修改此字段的内容。

Tip

See: Complete Code请参阅:完整代码

To view the complete code to insert a document encrypted with explicit encryption, see the Queryable Encryption sample application repository.要查看插入使用显式加密加密的文档的完整代码,请参阅可查询加密示例应用程序存储库

6

Retrieve Your Document with Encrypted Fields使用加密字段检索文档

Retrieve the document with encrypted fields you inserted in the Insert a Document with Encrypted Fields step of this guide through a query on an encrypted field:通过对加密字段的查询,检索您在本指南的插入带加密字段的文档步骤中插入的带加密字段文档:

const findPayload = await encryption.encrypt(patientId, {
algorithm: "Indexed",
keyId: dek1._id,
queryType: "equality",
contentionFactor: 1,
});

console.log("Finding a document with manually encrypted field:");
console.log(await encryptedColl.findOne({ patientId: findPayload }));

The output of the preceding code snippet should contain the following document:前面代码段的输出应该包含以下文档:

{
"__safeContent__": [
{
"Subtype": 0,
"Data": "LfaIuWm9o30MIGrK7GGUoStJMSNOjRgbxy5q2TPiDes="
}
],
"_id": "6303a770857952ca5e363fd2",
"firstName": "Jon",
"medications": ["Atorvastatin", "Levothyroxine"],
"patientId": 12345678
}
Tip

See: Complete Code请参阅:完整代码

To view the code to retrieve your document with encrypted fields, see the Queryable Encryption sample application repository.要查看用于检索具有加密字段的文档的代码,请参阅可查询加密示例应用程序存储库

Learn More了解更多信息

To view a tutorial on using Queryable Encryption with a remote KMS, see Tutorials.要查看有关在远程KMS中使用可查询加密的教程,请参阅教程

To learn how Queryable Encryption works, see Explicit Encryption.要了解可查询加密的工作原理,请参阅显式加密

To learn more about the topics mentioned in this guide, see the following links:要了解有关本指南中提到的主题的更多信息,请参阅以下链接: