Docs 菜单

将自动可查询加密与 KMIP 结合使用

本指南向您展示如何构建一个应用程序,实现 MongoDB 可查询加密功能以自动加密和解密文档字段,并使用符合密钥管理互操作性协议 (KMIP) 的密钥提供程序进行密钥管理。

在完成本指南中的步骤后,您应该具有:

  • 由符合 KMIP的提供商托管的客户主密钥

  • 有效的客户端应用程序,可使用客户主密钥插入具有加密字段的文档

提示

客户主密钥

要学习;了解有关客户主密钥的更多信息,请阅读密钥和密钥保管库文档。

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

提示

请参阅:完整应用程序

要查看此样本应用程序的完整代码,请选择与您的编程语言相对应的标签页,然后点击提供的链接。 每个样本应用程序存储库都包含一个 README.md文件,您可以使用该文件来了解如何设置环境和运行应用程序。

1

要将 MongoDB 驱动程序客户端连接到KMIP兼容密钥提供商,您必须配置KMIP兼容密钥提供商,使其接受客户端的 TLS 证书。

有关如何接受客户端证书的信息,请参阅符合KMIP的密钥提供商的文档。

2

客户端必须通过 TLS 连接到KMIP兼容密钥提供商,并提供KMIP兼容密钥提供商接受的客户端证书:

const tlsOptions = {
kmip: {
tlsCAFile: process.env["KMIP_TLS_CA_FILE"], // Path to your TLS CA file
tlsCertificateKeyFile: process.env["KMIP_TLS_CERT_FILE"], // Path to your TLS certificate key file
},
};
var tlsOptions = new Dictionary<string, SslSettings>();
var sslSettings = new SslSettings();
var clientCertificate = new X509Certificate2(_appSettings["Kmip:TlsCertP12"]!); // Full path to your client certificate p12 file
sslSettings.ClientCertificates = new[] { clientCertificate };
tlsOptions.Add("kmip", sslSettings);

重要

客户端证书必须采用 pks 12格式。 您可以使用 OpenSSL 将证书转换为 使用以下命令:

openssl pcks12 -export -out "<new pcks12 certificate>" -in "<certificate to convert>" \
-name "<new certificate name>" -password "<new certificate password>"
tlsOpts := map[string]interface{}{
"tlsCertificateKeyFile": os.Getenv("KMIP_TLS_CERT_ECDSA_FILE"), // Path to your client certificate file
"tlsCAFile": os.Getenv("KMIP_TLS_CA_ECDSA_FILE"), // Path to your KMIP certificate authority file
}
kmipConfig, err := options.BuildTLSConfig(tlsOpts)
if err != nil {
panic(fmt.Sprintf("Unable to retrieve certificates from your environment: %s\n", err))
}
tlsConfig := map[string]*tls.Config{
"kmip": kmipConfig,
}

重要

您必须使用带有 ECDSA 密钥 的证书 将Go驾驶员与 PyKMIP 结合使用时。

配置以下虚拟机选项以指定包含 KMIP TLS 证书的密钥库和信任库,并将它们添加到用于启动Java应用程序的命令中:

-Djavax.net.ssl.enabled=true
-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.keyStore=REPLACE-WITH-PATH-TO-PKC-KEYSTORE
-Djavax.net.ssl.keyStorePassword=REPLACE-WITH-KEYSTORE-PASSWORD
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.trustStore=REPLACE-WITH-PATH-TO-TRUSTSTORE
-Djavax.net.ssl.trustStorePassword=REPLACE-WITH-TRUSTSTORE-PASSWORD

注意

使用 SSLContext 配置客户端

如果您希望使用 SSL 上下文配置客户端应用程序,请使用 kmsProviderSslContextMap 方法。

const tlsOptions = {
kmip: {
tlsCAFile: process.env.KMIP_TLS_CA_FILE, // Path to your TLS CA file
tlsCertificateKeyFile: process.env.KMIP_TLS_CERT_FILE, // Path to your TLS certificate key file
},
};
tls_options = {
"kmip": {
"tlsCAFile": os.environ['KMIP_TLS_CA_FILE'], # Path to your TLS CA file
"tlsCertificateKeyFile": os.environ['KMIP_TLS_CERT_FILE'] # Path to your TLS certificate key file
}
}
1

本教程中的代码示例使用以下变量来执行 Queryable Encryption 工作流:

  • kmsProviderName - 您用于存储客户主密钥的KMS 。 在本教程中,将此变量设置为"kmip"

  • uri - 您的MongoDB 部署连接 URI。 在MONGODB_URI环境变量中设置连接 URI 或直接替换该值。

  • keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。将此变量设置为 "encryption"

  • keyVaultCollectionName - MongoDB 中将存储您的 DEK 的集合。 将此变量设置为"__keyVault"

  • keyVaultNamespace - MongoDB中将存储您的 DEK 的命名空间。 将此变量设置为keyVaultDatabaseNamekeyVaultCollectionName变量的值,并用句点分隔。

  • cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。将此变量设置为 "medicalRecords"

  • cryptoCollectionName - MongoDB 中将存储您的加密数据的集合。将此变量设置为 "patients"

您可以使用以下代码来声明这些变量:

// 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 - 您用来存储客户主密钥的 KMS。 在本教程中,请将此值设置为"kmip"

  • keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。 将keyVaultDatabaseName的值设置为"encryption"

  • keyVaultCollectionName - MongoDB 中将存储您的 DEK 的集合。 将keyVaultCollectionName的值设置为"__keyVault"

  • keyVaultNamespace - MongoDB 中将存储您的 DEK 的命名空间。 将keyVaultNamespace设置为新的CollectionNamespace对象,其名称是keyVaultDatabaseNamekeyVaultCollectionName变量的值,用句点分隔。

  • cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。 将encryptedDatabaseName的值设置为"medicalRecords"

  • encryptedCollectionName - MongoDB 中将存储您的加密数据的 collection。将encryptedCollectionName的值设置为"patients"

  • uri - 您的 MongoDB 部署连接 URI。 在appsettings.json文件中设置连接 URI 或直接替换该值。

您可以使用以下代码来声明这些变量:

// 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 - 您用于存储客户主密钥的KMS 。 在本教程中,将此变量设置为"kmip"

  • uri - 您的MongoDB 部署连接 URI。 在MONGODB_URI环境变量中设置连接 URI 或直接替换该值。

  • keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。将此变量设置为 "encryption"

  • keyVaultCollectionName - MongoDB 中将存储您的 DEK 的集合。 将此变量设置为"__keyVault"

  • keyVaultNamespace - MongoDB中将存储您的 DEK 的命名空间。 将此变量设置为keyVaultDatabaseNamekeyVaultCollectionName变量的值,并用句点分隔。

  • cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。将此变量设置为 "medicalRecords"

  • cryptoCollectionName - MongoDB 中将存储您的加密数据的集合。将此变量设置为 "patients"

您可以使用以下代码来声明这些变量:

// 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 - 您用于存储客户主密钥的KMS 。 在本教程中,将此变量设置为"kmip"

  • uri - 您的MongoDB 部署连接 URI。 在MONGODB_URI环境变量中设置连接 URI 或直接替换该值。

  • keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。将此变量设置为 "encryption"

  • keyVaultCollectionName - MongoDB 中将存储您的 DEK 的集合。 将此变量设置为"__keyVault"

  • keyVaultNamespace - MongoDB中将存储您的 DEK 的命名空间。 将此变量设置为keyVaultDatabaseNamekeyVaultCollectionName变量的值,并用句点分隔。

  • cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。将此变量设置为 "medicalRecords"

  • cryptoCollectionName - MongoDB 中将存储您的加密数据的集合。将此变量设置为 "patients"

您可以使用以下代码来声明这些变量:

// 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 - 您用于存储客户主密钥的KMS 。 在本教程中,将此变量设置为"kmip"

  • uri - 您的MongoDB 部署连接 URI。 在MONGODB_URI环境变量中设置连接 URI 或直接替换该值。

  • keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。将此变量设置为 "encryption"

  • keyVaultCollectionName - MongoDB 中将存储您的 DEK 的集合。 将此变量设置为"__keyVault"

  • keyVaultNamespace - MongoDB中将存储您的 DEK 的命名空间。 将此变量设置为keyVaultDatabaseNamekeyVaultCollectionName变量的值,并用句点分隔。

  • cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。将此变量设置为 "medicalRecords"

  • cryptoCollectionName - MongoDB 中将存储您的加密数据的集合。将此变量设置为 "patients"

您可以使用以下代码来声明这些变量:

// 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 - 您用来存储客户主密钥的KMS 。 在本教程中,将此变量设置为"kmip"

  • uri - 您的MongoDB 部署连接 URI。 在MONGODB_URI环境变量中设置连接 URI 或直接替换该值。

  • key_vault_database_name - MongoDB中将存储您的数据加密密钥 (DEK) 的数据库。 将此变量设置为"encryption"

  • key_vault_collection_name - MongoDB中将存储您的 DEK 的集合。 将此变量设置为"__keyVault"

  • key_vault_namespace - MongoDB中存储 DEK 的命名空间。 将此变量设置为key_vault_database_namekey_vault_collection_name变量的值,并用句点分隔。

  • encryption_database_name - MongoDB中将存储您的加密加密的数据库。 将此变量设置为"medicalRecords"

  • encryption_collection_name - MongoDB中将存储您的加密加密的集合。 将此变量设置为"patients"

您可以使用以下代码来声明这些变量:

# 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"

重要

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

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

提示

环境变量

本教程中的示例代码引用了您需要设置的环境变量。或者,您也可以直接在代码中替换这些值。

要了解如何设置这些环境变量,请参阅 GitHub 上的示例应用程序中包含的 README.md 文件。

提示

环境变量

本教程中的示例代码引用了您需要设置的环境变量。或者,您也可以直接在代码中替换这些值。

要了解如何设置这些环境变量,请参阅 GitHub 上的示例应用程序中包含的 README.md 文件。

提示

环境变量

本教程中的示例代码引用了您需要设置的环境变量。或者,您也可以直接在代码中替换这些值。

要了解如何设置这些环境变量,请参阅 GitHub 上的示例应用程序中包含的 README.md 文件。

提示

环境变量

本教程中的示例代码引用了您需要设置的环境变量。或者,您也可以直接在代码中替换这些值。

要了解如何设置这些环境变量,请参阅 GitHub 上的示例应用程序中包含的 README.md 文件。

提示

环境变量

本教程中的示例代码引用了您需要设置的环境变量。或者,您也可以直接在代码中替换这些值。

要了解如何设置这些环境变量,请参阅 GitHub 上的示例应用程序中包含的 README.md 文件。

提示

环境变量

本教程中的示例代码引用了您需要设置的环境变量。或者,您也可以直接在代码中替换这些值。

要了解如何设置这些环境变量,请参阅 GitHub 上的示例应用程序中包含的 README.md 文件。

2
1

创建一个变量,其中包含具有以下结构的符合 KMIP 的密钥提供商的端点:

kmsProviderCredentials = {
kmip: {
endpoint: process.env["KMIP_KMS_ENDPOINT"], // Your KMIP KMS endpoint
},
};
var kmsProviderCredentials = new Dictionary<string, IReadOnlyDictionary<string, object>>();
var kmsOptions = new Dictionary<string, object>
{
{ "endpoint", _appSettings["Kmip:KmsEndpoint"] } // Your KMIP KMS endpoint
};
kmsProviderCredentials.Add(kmsProvider, kmsOptions);
kmsProviderCredentials := map[string]map[string]interface{}{
"kmip": {
"endpoint": os.Getenv("KMIP_KMS_ENDPOINT"), // KMIP KMS endpoint
},
}
Map<String, Object> kmsProviderDetails = new HashMap<>();
kmsProviderDetails.put("endpoint", getEnv("KMIP_KMS_ENDPOINT")); // Your KMIP KMS endpoint
Map<String, Map<String, Object>> kmsProviderCredentials = new HashMap<String, Map<String, Object>>();
kmsProviderCredentials.put("kmip", kmsProviderDetails);
kmsProviders = {
kmip: {
endpoint: process.env.KMIP_KMS_ENDPOINT, // Your KMIP KMS endpoint
},
};
kms_provider_credentials = {
"kmip": {
"endpoint": os.environ['KMIP_KMS_ENDPOINT'] # Your KMIP KMS endpoint
}
}
2

创建一个空对象,如以下代码示例所示。 这会提示符合KMIP的提供商生成新的客户主密钥。

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

创建一个包含以下选项的autoEncryptionOptions对象:

  • 密钥保管库集合的命名空间

  • kmsProviderCredentials对象,其中包含您的KMIP端点

  • 您在“指定证书”步骤中创建的tlsOptions对象

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

创建一个包含以下选项的AutoEncryptionOptions对象:

  • 密钥保管库集合的命名空间

  • kmsProviderCredentials对象,其中包含您的KMIP端点

  • extraOptions 对象,其中包含指向您的自动加密共享库的路径

  • 您在“指定证书”步骤中创建的tlsOptions对象

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

创建一个包含以下选项的AutoEncryption对象:

  • 密钥保管库集合的命名空间

  • kmsProviderCredentials对象,其中包含您的KMIP端点

  • cryptSharedLibraryPath 对象,其中包含指向您的自动加密共享库的路径

  • 您在“指定证书”步骤中创建的tlsConfig对象

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).
SetTLSConfig(tlsConfig)

创建一个包含以下选项的AutoEncryptionSettings对象:

  • 密钥保管库集合的命名空间

  • kmsProviderCredentials对象,其中包含您的KMIP端点

  • extraOptions 对象,其中包含指向您的自动加密共享库的路径

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();

创建一个包含以下选项的autoEncryptionOptions对象:

  • 密钥保管库集合的命名空间

  • kmsProviders对象,其中包含您的KMIP端点

  • sharedLibraryPathOptions 对象,其中包含指向您的自动加密共享库的路径

  • 您在“指定证书”步骤中创建的tlsOptions对象

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

创建一个包含以下选项的AutoEncryptionOpts对象:

  • kms_provider_credentials对象,其中包含您的KMIP端点

  • 密钥保管库集合的命名空间

  • 自动加密共享库的路径

  • 您在“指定证书”步骤中创建的tls_options对象

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

注意

自动加密选项

自动加密选项向自动加密共享库提供配置信息,这将修改应用程序在访问加密字段时的行为。

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

4

要创建用于对集合中的数据进行加密和解密的客户端,请使用您的连接 URI 和自动加密选项实例化一个新的 MongoClient

const encryptedClient = Mongo(uri, autoEncryptionOptions);
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

如要加密字段,请将其添加到加密模式中。要启用对字段的查询,请添加“queries”属性。创建加密模式,如下所示:

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", "record.ssn" },
{ "bsonType", "string" },
{ "queries", new BsonDocument("queryType", "equality") }
},
new BsonDocument
{
{ "keyId", BsonNull.Value },
{ "path", "record.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",
}
]
}

注意

在前面的代码示例中,“ssn”和“billing”字段都经过加密,但只能查询“ssn”字段。

6

实例化 ClientEncryption 以访问加密辅助方法的 API。

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)
)

使用可通过ClientEncryption类访问的加密助手方法创建加密集合。 此方法自动为加密字段生成数据加密密钥并创建加密集合:

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

本教程的 C# 版本使用单独的类作为 Realm 数据模型来表示文档结构。将以下PatientPatientRecordPatientBilling类添加到您的项目中:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
[BsonIgnoreExtraElements]
public class Patient
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public PatientRecord Record { 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; }
}

添加这些类后,使用可通过ClientEncryption类访问的加密助手方法创建加密collection。此方法自动为字段生成数据加密密钥并创建加密collection:

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

提示

数据库与数据库名称

创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。

本教程的Go版本使用数据模型来表示文档结构。 将以下结构体添加到项目中以表示集合中的数据:

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"`
}

添加这些类后,使用可通过ClientEncryption类访问的加密助手方法创建加密collection。此方法自动为字段生成数据加密密钥并创建加密collection:

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

提示

数据库与数据库名称

创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。

使用可通过ClientEncryption类访问的加密助手方法创建加密集合。 此方法自动为加密字段生成数据加密密钥并创建加密集合:

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

提示

数据库与数据库名称

创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。

注意

导入 ClientEncryption

使用 Node.js 驱动程序 v6.0 及更高版本时,必须从 mongodb 导入 ClientEncryption

对于较早的驱动程序版本,请从 mongodb-client-encryption 导入 ClientEncryption

使用可通过ClientEncryption类访问的加密助手方法创建加密集合。 此方法自动为加密字段生成数据加密密钥并创建加密集合:

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

提示

数据库与数据库名称

创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。

使用可通过ClientEncryption类访问的加密助手方法创建加密集合。 此方法自动为加密字段生成数据加密密钥并创建加密集合:

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

提示

数据库与数据库名称

创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。

3

创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients 集合中,如以下示例所示:

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);

创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients 集合中,如以下示例所示:

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

创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients 集合中,如以下示例所示:

patientDocument := &PatientDocument{
PatientName: "John 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))
}

本教程使用 POJO 作为数据模型来表示文档结构。 要将应用程序设立为使用 POJO,请添加以下代码:

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

要学习;了解有关Java POJO 的更多信息,请参阅 维基百科文章“普通旧Java对象”。

本教程使用以下 POJO:

  • Patient

  • PatientRecord

  • PatientBilling

您可以 在完整Java应用程序的模型包中查看这些类。

将这些 POJO 类添加到您的应用程序中。 然后,创建描述患者个人信息的Patient实例。 使用加密客户端将其插入到patients集合中,如以下示例所示:

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);

创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients 集合中,如以下示例所示:

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);

创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients 集合中,如以下示例所示:

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

下面的代码示例对加密字段执行查找查询,并打印解密后的数据:

const findResult = await encryptedCollection.findOne({
"patientRecord.ssn": "987-65-4320",
});
console.log(findResult);
var ssnFilter = Builders<Patient>.Filter.Eq("record.ssn", patient.Record.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)

上述代码示例的输出应类似于以下内容:

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

警告

不要修改 __safeContent__ 字段

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

如需了解 Queryable Encryption 的工作原理,请参阅基础知识

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

  • 有关 Queryable Encryption 组件的更多信息,请参阅参考页面。

  • 访问密钥和密钥保管库页面,了解客户主密钥和数据加密密钥的工作原理。

  • KMS 提供商页面上查看 KMS 提供商如何管理您的可查询加密密钥。