Docs 菜单
Docs 主页
/
MongoDB Manual
/ / / / /

使用显式加密

在此页面上

  • Overview
  • 开始之前
  • 步骤
  • 创建客户主密钥
  • 在密钥保管库集合上创建唯一索引
  • 创建你的数据加密密钥和加密collection
  • 配置 MongoClient 以进行加密读取和写入
  • 插入具有加密字段的文档
  • 检索加密文档
  • 了解详情

本指南向您展示如何使用显式加密和 MongoDB 驱动程序来加密文档。

完成本指南后,您应该能够配置驱动程序,使用显式加密对文档中的字段进行加密。 有了这些知识,您应该能够创建使用显式加密的客户端应用程序。具有自动解密功能。

重要

请勿在生产中使用此应用程序

由于此示例应用程序在应用程序的文件系统上存储了加密密钥,因此您可能会遇到未经授权访问该密钥或丢失解密数据的密钥的风险。

要查看演示如何创建使用远程密钥管理系统且启用了可查询Queryable Encryption的应用程序的教程,请参阅教程。

要完成并运行本指南中的代码,您需要按照安装要求页面中的步骤来设置开发环境。

提示

请参阅:完整应用程序

要查看您在本指南中创建的应用程序的完整代码,请选择与您的首选 MongoDB 驱动程序对应的标签页,然后点击提供的链接:

1

您必须创建客户主密钥 ( 客户主密钥 ) 才能执行Queryable Encryption。

创建 96 字节的客户主密钥并将其保存到文件 master-key.txt中:

openssl rand 96 > master-key.txt

注意

使用编程语言创建客户主密钥

如果您更愿意使用首选编程语言生成 集合扫描 ,则可以在Github 上查看演示如何以本指南支持的每种语言生成客户主密钥的代码片段。

警告

请勿在生产环境中使用本地密钥文件

文件系统中的本地密钥文件不安全,不建议用于生产环境。相反,应将客户主密钥存储在远程密钥管理系统 (KMS) 中。

要了解如何在 Queryable Encryption 实施中使用远程 KMS,请参阅教程指南。

2

在你的encryption.__keyVaultcollection中的keyAltNames字段上创建唯一索引。

选择与所需的 MongoDB 驱动程序对应的标签页:

var connectionString = "<Your MongoDB URI>";
var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
var keyVaultClient = new MongoClient(connectionString);
var indexOptions = new CreateIndexOptions<BsonDocument>
{
Unique = true,
PartialFilterExpression = new BsonDocument
{{"keyAltNames", new BsonDocument {{"$exists", new BsonBoolean(true)}}}}
};
var builder = Builders<BsonDocument>.IndexKeys;
var indexKeysDocument = builder.Ascending("keyAltNames");
var indexModel = new CreateIndexModel<BsonDocument>(indexKeysDocument, indexOptions);
var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);
var keyVaultCollection = keyVaultDatabase.GetCollection<BsonDocument>(keyVaultNamespace.CollectionName);
keyVaultCollection.Indexes.CreateOne(indexModel);
uri := "<Your MongoDB URI>"
keyVaultClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
if err != nil {
return fmt.Errorf("Connect error for regular client: %v", err)
}
defer func() {
_ = keyVaultClient.Disconnect(context.TODO())
}()
keyVaultDb := "encryption"
keyVaultColl := "__keyVault"
keyVaultNamespace := keyVaultDb + "." + keyVaultColl
keyVaultIndex := mongo.IndexModel{
Keys: bson.D{{"keyAltNames", 1}},
Options: options.Index().
SetUnique(true).
SetPartialFilterExpression(bson.D{
{"keyAltNames", bson.D{
{"$exists", true},
}},
}),
}
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
if err = keyVaultClient.Database(keyVaultDb).Collection(keyVaultColl).Drop(context.TODO()); err != nil {
log.Fatalf("Collection.Drop error: %v", err)
}
_, err = keyVaultClient.Database(keyVaultDb).Collection(keyVaultColl).Indexes().CreateOne(context.TODO(), keyVaultIndex)
if err != nil {
panic(err)
}
String keyVaultDb = "encryption";
String keyVaultColl = "__keyVault";
MongoClient keyVaultClient = MongoClients.create(connectionString);
String encryptedDbName = "medicalRecords";
String encryptedCollName = "patients";
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
keyVaultClient.getDatabase(keyVaultDb).getCollection(keyVaultColl).drop();
MongoCollection keyVaultCollection = keyVaultClient.getDatabase(keyVaultDb).getCollection(keyVaultColl);
IndexOptions indexOpts = new IndexOptions().partialFilterExpression(new BsonDocument("keyAltNames", new BsonDocument("$exists", new BsonBoolean(true) ))).unique(true);
keyVaultCollection.createIndex(new BsonDocument("keyAltNames", new BsonInt32(1)), indexOpts);
keyVaultClient.close();
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 } },
}
);
connection_string = "<your connection string here>"
key_vault_coll = "__keyVault"
key_vault_db = "encryption"
key_vault_namespace = f"{key_vault_db}.{key_vault_coll}"
key_vault_client = MongoClient(connection_string)
# Drop the Key Vault Collection in case you created this collection
# in a previous run of this application.
key_vault_client.drop_database(key_vault_db)
key_vault_client[key_vault_db][key_vault_coll].create_index(
[("keyAltNames", ASCENDING)],
unique=True,
partialFilterExpression={"keyAltNames": {"$exists": True}},
)
3
1

检索您在本指南的创建客户主密钥步骤中生成的客户主密钥文件的内容。

客户主密钥值传递到您的 KMS 提供商设置。The client uses these settings to discover the CMK. 将提供程序名称设置为local以通知驱动程序您正在使用本地密钥提供程序。

选择与所需的 MongoDB 驱动程序对应的标签页:

var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
const string provider = "local";
var localMasterKeyBase64Read = File.ReadAllText("master-key.txt");
var localMasterKeyBytes = Convert.FromBase64String(localMasterKeyBase64Read);
var localOptions = new Dictionary<string, object>
{
{"key", localMasterKeyBytes}
};
kmsProviders.Add(provider, localOptions);
key, err := ioutil.ReadFile("master-key.txt")
if err != nil {
log.Fatalf("Could not read the key from master-key.txt: %v", err)
}
provider := "local"
kmsProviders := map[string]map[string]interface{}{"local": {"key": key}}
String kmsProvider = "local";
String path = "master-key.txt";
byte[] localMasterKeyRead = new byte[96];
try (FileInputStream fis = new FileInputStream(path)) {
if (fis.read(localMasterKeyRead) < 96)
throw new Exception("Expected to read 96 bytes from file");
}
Map<String, Object> keyMap = new HashMap<String, Object>();
keyMap.put("key", localMasterKeyRead);
Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
kmsProviders.put("local", keyMap);
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,
},
};
provider = "local"
path = "./master-key.txt"
# WARNING: Do not use a local key file in a production application
with open(path, "rb") as f:
local_master_key = f.read()
kms_providers = {
"local": {
"key": local_master_key # local_master_key variable from the previous step
},
}
2

使用 MongoDB 连接字符串和密钥保管库集合命名空间构建客户端,并创建数据加密密钥:

注意

密钥保管库集合命名空间权限

密钥保管库集合位于encryption.__keyVault命名空间中。 确保应用程序用于连接到 MongoDB 的数据库用户对此命名空间具有ReadWrite权限。

var clientEncryptionOptions = new ClientEncryptionOptions(
keyVaultClient,
keyVaultNamespace,
kmsProviders: kmsProviders
);
var clientEncryption = new ClientEncryption(clientEncryptionOptions);
var dataKeyOptions1 = new DataKeyOptions(alternateKeyNames: new List<string> { "dataKey1" });
var dataKeyOptions2 = new DataKeyOptions(alternateKeyNames: new List<string> { "dataKey2" });
BsonBinaryData CreateKeyGetID(DataKeyOptions options)
{
var dateKeyGuid = clientEncryption.CreateDataKey(provider, options, CancellationToken.None);
return new BsonBinaryData(dateKeyGuid, GuidRepresentation.Standard);
}
var dataKeyId1 = CreateKeyGetID(dataKeyOptions1);
var dataKeyId2 = CreateKeyGetID(dataKeyOptions2);
var dataKeyId3 = CreateKeyGetID(dataKeyOptions3);
var dataKeyId4 = CreateKeyGetID(dataKeyOptions4);
clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(keyVaultNamespace).
SetKmsProviders(kmsProviders)
clientEnc, err := mongo.NewClientEncryption(keyVaultClient, clientEncryptionOpts)
if err != nil {
return fmt.Errorf("NewClientEncryption error %v", err)
}
defer func() {
_ = clientEnc.Close(context.TODO())
}()
dataKeyOpts1 := options.DataKey().
SetKeyAltNames([]string{"demoDataKey1"})
dataKeyID1, err := clientEnc.CreateDataKey(context.TODO(), provider, dataKeyOpts1)
if err != nil {
return fmt.Errorf("create data key error %v", err)
}
dataKeyOpts2 := options.DataKey().
SetKeyAltNames([]string{"demoDataKey2"})
dataKeyID2, err := clientEnc.CreateDataKey(context.TODO(), provider, dataKeyOpts2)
if err != nil {
return fmt.Errorf("create data key error %v", err)
}
String keyVaultNamespace = keyVaultDb + "." + keyVaultColl;
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.build())
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.build();
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
List<String> keyAlts1 = new ArrayList<String>();
keyAlts1.add("dataKey1");
BsonBinary dataKeyId1 = clientEncryption.createDataKey(kmsProvider, new DataKeyOptions()
.keyAltNames(keyAlts1));
List<String> keyAlts2 = new ArrayList<String>();
keyAlts2.add("dataKey2");
BsonBinary dataKeyId2 = clientEncryption.createDataKey(kmsProvider, new DataKeyOptions()
.keyAltNames(keyAlts2));
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"],
});
client = MongoClient(connection_string)
client_encryption = ClientEncryption(
kms_providers, # pass in the kms_providers variable from the previous step
key_vault_namespace,
client,
CodecOptions(uuid_representation=STANDARD),
)
data_key_id_1 = client_encryption.create_data_key(provider, key_alt_names=["dataKey1"])
data_key_id_2 = client_encryption.create_data_key(provider, key_alt_names=["dataKey2"])
3

使用已启用 Queryable EncryptionMongoClient 的实例指定必须加密的字段并创建加密的 collection:

var encryptedCollectionNamespace = CollectionNamespace.FromFullName("medicalRecords.patients");
var encryptedFieldsMap = new Dictionary<string, BsonDocument>
{
{
encryptedCollectionNamespace.FullName, new BsonDocument
{
{
"fields", new BsonArray
{
new BsonDocument
{
{"keyId", dataKeyId1},
{"path", new BsonString("patientId")},
{"bsonType", new BsonString("int")},
{
"queries", new BsonDocument
{
{"queryType", new BsonString("equality")}
}
}
},
new BsonDocument
{
{"keyId", dataKeyId2},
{"path", new BsonString("medications")},
{"bsonType", new BsonString("array")},
},
}
}
}
}
};
var extraOptions = new Dictionary<string, object>()
{
{ "cryptSharedLibPath", "<path to crypt_shared library>" },
};
var autoEncryptionOptions = new AutoEncryptionOptions(
keyVaultNamespace,
kmsProviders,
encryptedFieldsMap: encryptedFieldsMap,
extraOptions: extraOptions);
var clientSettings = MongoClientSettings.FromConnectionString(connectionString);
clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
var secureClient = new MongoClient(clientSettings);
var encryptedDatabase = secureClient.GetDatabase(encryptedCollectionNamespace.DatabaseNamespace.DatabaseName);
// Drop the encrypted collection in case you created this collection
// in a previous run of this application.
encryptedDatabase.DropCollection(encryptedCollectionNamespace.CollectionName);
encryptedDatabase.CreateCollection(encryptedCollectionNamespace.CollectionName);
Console.WriteLine("Created encrypted collection!");
dbName := "medicalRecords"
collName := "patients"
encNamespace := (dbName + "." + collName)
encryptedFieldsMap := bson.M{
encNamespace: bson.M{
"fields": []bson.M{
{
"path": "patientId",
"bsonType": "int",
"keyId": dataKeyID1,
"queries": []bson.M{
{
"queryType": "equality",
},
},
},
{
"path": "medications",
"bsonType": "array",
"keyId": dataKeyID2,
},
},
},
}
extraOptions := map[string]interface{}{
"cryptSharedLibPath": "<Your Crypt Shared lib Path>",
}
autoEncryptionOpts := options.AutoEncryption().
SetKmsProviders(kmsProviders).
SetKeyVaultNamespace(keyVaultNamespace).
SetEncryptedFieldsMap(encryptedFieldsMap).
SetExtraOptions(extraOptions)
secureClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri).SetAutoEncryptionOptions(autoEncryptionOpts))
if err != nil {
return fmt.Errorf("Connect error for encrypted client: %v", err)
}
defer func() {
_ = secureClient.Disconnect(context.TODO())
}()
// Drop the encrypted collection in case you created this collection
// in a previous run of this application.
if err = secureClient.Database(dbName).Collection(collName).Drop(context.TODO()); err != nil {
log.Fatalf("Collection.Drop error: %v", err)
}
err = secureClient.Database(dbName).CreateCollection(context.TODO(), collName)
if err != nil {
return fmt.Errorf("Error creating collection: %v", err)
}
String encryptedNameSpace = encryptedDbName + "." + encryptedCollName;
BsonDocument encFields = new BsonDocument().append("fields",
new BsonArray(Arrays.asList(
new BsonDocument().append("keyId", dataKeyId1)
.append("path", new BsonString("patientId"))
.append("bsonType", new BsonString("int"))
.append("queries", new BsonDocument().append("queryType", new BsonString("equality"))),
new BsonDocument().append("keyId", dataKeyId2)
.append("path", new BsonString("medications"))
.append("bsonType", new BsonString("array")),
)));
Map<String, BsonDocument> encryptedFieldsMap = new HashMap<String, BsonDocument>();
encryptedFieldsMap.put(encryptedNameSpace, encFields);
Map<String, Object> extraOptions = new HashMap<String, Object>();
extraOptions.put("cryptSharedLibPath", "<path to crypt_shared>");
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.autoEncryptionSettings(AutoEncryptionSettings.builder()
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.encryptedFieldsMap(encryptedFieldsMap)
.extraOptions(extraOptions)
.build())
.build();
MongoClient mongoClientSecure = MongoClients.create(clientSettings);
MongoDatabase encDb = mongoClientSecure.getDatabase(encryptedDbName);
// Drop the encrypted collection in case you created this collection
// in a previous run of this application.
encDb.getCollection(encryptedCollName).drop();
encDb.createCollection(encryptedCollName);
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!");
encrypted_db_name = "medicalRecords"
encrypted_coll_name = "patients"
encrypted_fields_map = {
f"{encrypted_db_name}.{encrypted_coll_name}": {
"fields": [
{
"keyId": data_key_id_1,
"path": "patientId",
"bsonType": "int",
"queries": {"queryType": "equality"},
},
{
"keyId": data_key_id_2,
"path": "medications",
"bsonType": "array",
},
],
},
}
key_vault_namespace = "encryption.__keyVault"
auto_encryption = AutoEncryptionOpts(
kms_providers,
key_vault_namespace,
encrypted_fields_map=encrypted_fields_map,
schema_map=None,
crypt_shared_lib_path="<path to FLE Shared Library>",
)
secure_client = MongoClient(connection_string, auto_encryption_opts=auto_encryption)
# Drop the encrypted collection in case you created this collection
# in a previous run of this application.
secure_client.drop_database(encrypted_db_name)
encrypted_db = secure_client[encrypted_db_name]
encrypted_db.create_collection(encrypted_coll_name)
print("Created encrypted collection!")

本节中代码的输出应类似于以下内容:

Created encrypted collection!

提示

请参阅:完整代码

要查看制作数据加密密钥的完整代码,请参阅 Queryable Encryption 示例应用程序存储库。

要查看制作数据加密密钥的完整代码,请参阅 Queryable Encryption 示例应用程序存储库。

要查看制作数据加密密钥的完整代码,请参阅 Queryable Encryption 示例应用程序存储库。

要查看制作数据加密密钥的完整代码,请参阅 Queryable Encryption 示例应用程序存储库。

要查看制作数据加密密钥的完整代码,请参阅 Queryable Encryption 示例应用程序存储库。

4
1

指定 encryption.__keyVault 以作为密钥保管库集合命名空间。

var connectionString = "<Your MongoDB URI>";
var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
var coll = "patients";
var db = "medicalRecords";
keyVaultColl := "__keyVault"
keyVaultDb := "encryption"
keyVaultNamespace := keyVaultDb + "." + keyVaultColl
dbName := "medicalRecords"
collName := "patients"
String db = "medicalRecords";
String coll = "patients";
String keyVaultDb = "encryption";
String keyVaultColl = "__keyVault";
String keyVaultNamespace = String.format("%1$s.%2$s", keyVaultDb, keyVaultColl);
String connectionString = "<Your MongoDB URI>";
const eDB = "encryption";
const eKV = "__keyVault";
const keyVaultNamespace = `${eDB}.${eKV}`;
const secretDB = "medicalRecords";
const secretCollection = "patients";
key_vault_namespace = "encryption.__keyVault"
key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1)
2

指定 KMS 提供商并以内联方式指定客户主密钥:

var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
const string provider = "local";
const string localMasterKeyPath = "master-key.txt";
var localMasterKeyBase64Read = File.ReadAllText(localMasterKeyPath);
var localMasterKeyBytes = Convert.FromBase64String(localMasterKeyBase64Read);
var localOptions = new Dictionary<string, object>
{
{"key", localMasterKeyBytes}
};
kmsProviders.Add(provider, localOptions);
key, err := ioutil.ReadFile("master-key.txt")
if err != nil {
log.Fatalf("Could not read the key from master-key.txt: %v", err)
}
kmsProviders := map[string]map[string]interface{}{"local": {"key": key}}
String kmsProvider = "local";
String path = "master-key.txt";
byte[] localMasterKeyRead = new byte[96];
try (FileInputStream fis = new FileInputStream(path)) {
if (fis.read(localMasterKeyRead) < 96)
throw new Exception("Expected to read 96 bytes from file");
}
Map<String, Object> keyMap = new HashMap<>();
keyMap.put("key", localMasterKeyRead);
Map<String, Map<String, Object>> kmsProviders = new HashMap<>();
kmsProviders.put(kmsProvider, keyMap);
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,
},
};
path = "./master-key.txt"
with open(path, "rb") as f:
local_master_key = f.read()
kms_providers = {
"local": {
"key": local_master_key # local_master_key variable from the previous step
},
}
3

检索在本指南的“创建数据加密密钥”步骤中创建的数据加密密钥

var regularClient = new MongoClient(connectionString);
var keyVaultCollection = regularClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName)
.GetCollection<BsonDocument>(keyVaultNamespace.CollectionName);
Guid GetKeyId(string altName)
{
var filter = Builders<BsonDocument>.Filter.Eq<BsonString>("keyAltNames", altName);
return keyVaultCollection.Find(filter).First<BsonDocument>()["_id"].AsGuid;
}
var dataKeyId1 = GetKeyId("dataKey1");
var dataKeyId2 = GetKeyId("dataKey2");
uri := "<Your MongoDB URI>"
regularClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
if err != nil {
panic(fmt.Errorf("Client connect error %v", err))
}
var foundDoc1 bson.M
err = regularClient.Database(keyVaultDb).Collection(keyVaultColl).FindOne(context.TODO(), bson.D{{"keyAltNames", "demoDataKey1"}}).Decode(&foundDoc1)
if err != nil {
panic(err)
}
var dataKeyID1 = foundDoc1["_id"].(primitive.Binary)
var foundDoc2 bson.M
err = regularClient.Database(keyVaultDb).Collection(keyVaultColl).FindOne(context.TODO(), bson.D{{"keyAltNames", "demoDataKey2"}}).Decode(&foundDoc2)
if err != nil {
panic(err)
}
var dataKeyID2 = foundDoc2["_id"].(primitive.Binary)
MongoClient client = MongoClients.create(connectionString);
MongoCollection<Document> keyVaultClient = client.getDatabase(keyVaultDb).getCollection(keyVaultColl);
BsonBinary dataKeyId1 = new BsonBinary(BsonBinarySubType.UUID_STANDARD, keyVaultClient.find(eq("keyAltNames", "dataKey1")).first().get("_id", Binary.class).getData());
BsonBinary dataKeyId2 = new BsonBinary(BsonBinarySubType.UUID_STANDARD, keyVaultClient.find(eq("keyAltNames", "dataKey2")).first().get("_id", Binary.class).getData());
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" });
connection_string = "<your connection string here>"
client = MongoClient(connection_string)
key_vault = client[key_vault_db_name][key_vault_coll_name]
data_key_id_1 = key_vault.find_one({"keyAltNames": "dataKey1"})["_id"]
data_key_id_2 = key_vault.find_one({"keyAltNames": "dataKey2"})["_id"]
4
var extraOptions = new Dictionary<string, object>()
{
{"cryptSharedLibPath", "<path to crypt_shared library>"},
};
extraOptions := map[string]interface{}{
"cryptSharedLibPath": "<path to crypt_shared library>",
}
Map<String, Object> extraOptions = new HashMap<>();
extraOptions.put("cryptSharedLibPath", "<path to crypt_shared library>");
const extraOptions = {
cryptSharedLibPath: "<path to crypt_shared library>",
};
opts = AutoEncryptionOpts(
kms_providers,
key_vault.full_name,
bypass_query_analysis=True,
key_vault_client=client,
crypt_shared_lib_path="<path to FLE Shared Library>",
)

提示

了解详情

要了解有关此路径引用的库的更多信息,请参阅用于 Queryable Encryption 的自动加密共享库页面。

5

使用以下自动加密设置实例化MongoClient对象:

var clientSettings = MongoClientSettings.FromConnectionString(connectionString);
var autoEncryptionOptions = new AutoEncryptionOptions(
keyVaultNamespace,
kmsProviders,
bypassQueryAnalysis: true,
extraOptions: extraOptions);
clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
var secureClient = new MongoClient(clientSettings);
var collection = secureClient.GetDatabase(db).GetCollection<BsonDocument>(coll);
autoEncryptionOpts := options.AutoEncryption().
SetKmsProviders(kmsProviders).
SetKeyVaultNamespace(keyVaultNamespace).
SetExtraOptions(extraOptions).
SetBypassQueryAnalysis(true)
secureClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri).SetAutoEncryptionOptions(autoEncryptionOpts))
if err != nil {
return fmt.Errorf("Connect error for encrypted client: %v", err)
}
defer func() {
_ = secureClient.Disconnect(context.TODO())
}()
var coll = secureClient.Database(dbName).Collection(collName)
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.autoEncryptionSettings(AutoEncryptionSettings.builder()
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.extraOptions(extraOptions)
.bypassQueryAnalysis(true)
.build())
.build();
MongoClient mongoClientSecure = MongoClients.create(clientSettings);
const encryptedClient = new MongoClient(uri, {
autoEncryption: {
kmsProviders: kmsProviders,
keyVaultNamespace: keyVaultNamespace,
bypassQueryAnalysis: true,
keyVaultClient: unencryptedClient,
extraOptions: extraOptions,
},
});
await encryptedClient.connect();
encrypted_client = MongoClient(connection_string, auto_encryption_opts=opts)
db = encrypted_client.medicalRecords
coll = db.patients

注意

自动解密

MongoClient我们使用启用了自动加密的实例来执行自动解密。

要了解有关使用自动解密的显式加密的更多信息,请参阅“基础知识”部分。

6

按如下方式实例化一个ClientEncryption对象:

var clientEncryptionOptions = new ClientEncryptionOptions(
keyVaultClient: regularClient,
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders
);
var clientEncryption = new ClientEncryption(clientEncryptionOptions);
clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(keyVaultNamespace).SetKmsProviders(kmsProviders)
clientEnc, err := mongo.NewClientEncryption(regularClient, clientEncryptionOpts)
if err != nil {
panic(fmt.Errorf("NewClientEncryption error %v", err))
}
defer func() {
_ = clientEnc.Close(context.TODO())
}()
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.build())
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.build();
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
const encryption = new ClientEncryption(unencryptedClient, {
keyVaultNamespace,
kmsProviders,
});
client_encryption = ClientEncryption(
kms_providers, key_vault_namespace, client, client.codec_options
)
5

使用已启用 Queryable Encryption 的实例MongoClient,通过以下代码段将加密文档插入到命名空间medicalRecords.patients中:

var patientId = 12345678;
var medications = new BsonArray
{
new BsonString("Atorvastatin"),
new BsonString("Levothyroxine")
};
var indexedEncrypted = clientEncryption.Encrypt(
patientId,
new EncryptOptions(algorithm: "Indexed", keyId: dataKeyId1, contentionFactor: 1),
CancellationToken.None);
var unindexedEncrypted = clientEncryption.Encrypt(
medications,
new EncryptOptions(algorithm: "Unindexed", keyId: dataKeyId2),
CancellationToken.None);
collection.InsertOne(new BsonDocument { { "firstName", "Jon" }, { "patientId", indexedEncrypted }, { "medications", unindexedEncrypted } });
patientIdRawValueType, patientIdRawValueData, err := bson.MarshalValue(12345678)
if err != nil {
panic(err)
}
patientIdRawValue := bson.RawValue{Type: patientIdRawValueType, Value: patientIdRawValueData}
patientIdEncryptionOpts := options.Encrypt().
SetAlgorithm("Indexed").
SetKeyID(dataKeyID1).
SetContentionFactor(1)
patientIdEncryptedField, err := clientEnc.Encrypt(
context.TODO(),
patientIdRawValue,
patientIdEncryptionOpts)
if err != nil {
panic(err)
}
medicationsRawValueType, medicationsRawValueData, err := bson.MarshalValue([]string{"Atorvastatin", "Levothyroxine"})
if err != nil {
panic(err)
}
medicationsRawValue := bson.RawValue{Type: medicationsRawValueType, Value: medicationsRawValueData}
medicationsEncryptionOpts := options.Encrypt().
SetAlgorithm("Unindexed").
SetKeyID(dataKeyID2)
medicationsEncryptedField, err := clientEnc.Encrypt(
context.TODO(),
medicationsRawValue,
medicationsEncryptionOpts)
if err != nil {
panic(err)
}
_, err = coll.InsertOne(
context.TODO(),
bson.D{{"firstName", "Jon"}, {"patientId", patientIdEncryptedField}, {"medications", medicationsEncryptedField}})
if err != nil {
panic(err)
}
BsonInt32 patientId = new BsonInt32(12345678);
ArrayList<BsonString> medications = new ArrayList<>();
medications.add(new BsonString("Atorvastatin"));
medications.add(new BsonString("Levothyroxine"));
BsonBinary indexedEncrypted = clientEncryption.encrypt(patientId, new EncryptOptions("Indexed").keyId(dataKeyId1).contentionFactor(1L));
BsonBinary unindexedEncrypted = clientEncryption.encrypt(new BsonArray(medications), new EncryptOptions("Unindexed").keyId(dataKeyId2));
MongoCollection<BsonDocument> collection = mongoClientSecure.getDatabase(db).getCollection(coll, BsonDocument.class);
collection.insertOne(new BsonDocument("firstName", new BsonString("Jon")).append("patientId", indexedEncrypted).append("medications", unindexedEncrypted));
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,
});
patientId = 12345678
medications = ["Atorvastatin", "Levothyroxine"]
indexed_insert_payload = client_encryption.encrypt(
patientId, Algorithm.INDEXED, data_key_id_1, contention_factor=1
)
unindexed_insert_payload = client_encryption.encrypt(
medications, Algorithm.UNINDEXED, data_key_id_2
)
coll.insert_one(
{
"firstName": "Jon",
"patientId": indexed_insert_payload,
"medications": unindexed_insert_payload,
}
)

插入文档时,启用了 Queryable Encryption 的客户端会对文档的字段进行加密,如下所示:

{
"_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"
}
}
]
}

警告

不要修改 __safeContent__ 字段

__safeContent__ 字段对于 Queryable Encryption 至关重要。请勿修改此字段的内容。

提示

请参阅:完整代码

要查看插入通过显式加密加密的文档的完整代码,请参阅 可查询Queryable Encryption 示例应用程序存储库。

要查看插入通过显式加密加密的文档的完整代码,请参阅 可查询Queryable Encryption 示例应用程序存储库。

要查看插入通过显式加密加密的文档的完整代码,请参阅 可查询Queryable Encryption 示例应用程序存储库。

要查看插入通过显式加密加密的文档的完整代码,请参阅 可查询Queryable Encryption 示例应用程序存储库。

要查看插入通过显式加密加密的文档的完整代码,请参阅 可查询Queryable Encryption 示例应用程序存储库。

6

通过对加密字段进行查询,检索在本指南的“插入具有加密字段的文档”步骤中插入的加密文档:

var findPayload = clientEncryption.Encrypt(
patientId,
new EncryptOptions(algorithm: "Indexed", keyId: dataKeyId1, queryType: "equality", contentionFactor: 1),
CancellationToken.None);
var doc = collection.Find(new BsonDocument { { "patientId", findPayload } }).Single();
Console.WriteLine($"Encrypted document: {doc}");
findPayloadRawValueType, findPayloadRawValueData, err := bson.MarshalValue(12345678)
if err != nil {
panic(err)
}
findPayloadRawValue := bson.RawValue{Type: findPayloadRawValueType, Value: findPayloadRawValueData}
findPayloadEncryptionOpts := options.Encrypt().
SetAlgorithm("Indexed").
SetKeyID(dataKeyID1).
SetQueryType("equality").
SetContentionFactor(1)
findPayloadEncryptedField, err := clientEnc.Encrypt(
context.TODO(),
findPayloadRawValue,
findPayloadEncryptionOpts)
if err != nil {
panic(err)
}
var resultSecure bson.M
coll.FindOne(context.TODO(), bson.D{{"firstName", findPayloadEncryptedField}}).Decode(&resultSecure)
if err != nil {
panic(err)
}
outputSecure, err := json.MarshalIndent(resultSecure, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("\nFound document searching on explicitly encrypted field:\n%s\n", outputSecure)
BsonBinary findPayloadEncrypted = clientEncryption.encrypt(patientId, new EncryptOptions("Indexed").keyId(dataKeyId1).queryType("equality").contentionFactor(1L));
BsonDocument result = collection.find(eq("patientId", findPayloadEncrypted)).first();
System.out.println("Finding a document with manually encrypted field: " + result.toJson());
const findPayload = await encryption.encrypt(patientId, {
algorithm: "Indexed",
keyId: dek1._id,
queryType: "equality",
contentionFactor: 1,
});
console.log("Finding a document with manually encrypted field:");
find_payload = client_encryption.encrypt(
patientId,
Algorithm.INDEXED,
data_key_id_1,
query_type=QueryType.EQUALITY,
contention_factor=1,
)
doc = coll.find_one({"encryptedIndexed": find_payload})
print("\nReturned document:\n")
pprint.pprint(doc)

上述代码片段的输出应包含以下文档:

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

提示

请参阅:完整代码

要查看用于检索加密文档的代码,请参阅 Queryable Encryption示例应用程序存储库。

要查看用于检索加密文档的代码,请参阅 Queryable Encryption示例应用程序存储库。

要查看用于检索加密文档的代码,请参阅 Queryable Encryption示例应用程序存储库。

要查看用于检索加密文档的代码,请参阅 Queryable Encryption示例应用程序存储库。

要查看用于检索加密文档的代码,请参阅 Queryable Encryption示例应用程序存储库。

要查看有关将 Queryable Encryption 与远程 KMS 结合使用的教程,请参阅教程。

要了解Queryable Encryption的工作原理,请参阅显式加密。

如需详细了解本指南中提到的主题,请参阅以下链接:

后退

使用 KMIP