文档菜单
文档首页
/
MongoDB 手册
/ / / / /

加密密钥管理

在本页

  • 加密组件
  • 支持的关键管理服务
  • 管理数据加密密钥的备用名称
  • 使用备用名称创建数据加密密钥
  • 在自动加密方案中使用密钥备用名称
  • 程序:使用Mongo Shell旋转加密密钥
  • 删除数据加密密钥
  • 了解更多信息

在本指南中,您可以了解如何使用密钥管理系统(KMS)管理您的客户端字段级加密(CSFLE)启用应用程序中的加密密钥。

MongoDB使用以下组件执行客户端字段级加密

  • 数据加密密钥(DEK

  • 客户主密钥(CMK

  • 密钥库集合

  • 密钥管理系统(KMS

有关密钥和密钥库的更多信息,请参阅加密密钥和密钥库.

客户端字段级加密支持以下密钥管理系统提供商

  • Amazon Web Services KMS

  • Azure Key Vault

  • Google Cloud KMS

  • 任何符合KMIP的密钥管理系统

  • 本地密钥提供者

默认的KMIP协议版本为1.2。您可以在MongoDB服务器配置文件中配置使用KMIP版本1.0或1.1。配置文件。

要了解更多关于这些提供者的信息,包括显示应用程序如何使用它们进行客户端字段级加密的图表,请参阅KMS提供者。

您可以为数据加密密钥分配备用名称,以便更容易地引用。分配备用名称允许您执行以下操作

  • 通过除DEK字段的_id字段以外的其他方式引用。

  • 在运行时动态分配DEK。

重要

先决条件

在添加新的密钥备用名称之前,您必须在对keyAltNames字段创建部分唯一索引。此索引应具有针对keyAltNames存在的文档的partialFilterExpression

客户端字段级加密依赖于服务器强制执行密钥备用名称的唯一性。

要了解如何创建部分索引,请参阅部分索引。

以下示例创建了一个具有备用名称的数据加密密钥。选择与您的驱动程序语言对应的选项卡

var autoEncryptionOpts = {
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders,
};
var encryptedClient = Mongo(
connectionString,
autoEncryptionOpts
);
var clientEncryption = encryptedClient.getClientEncryption();
var masterKey = {
"<Your dataKeyOpts Key>": "<Your dataKeyOpts Value>",
};
var keyVault = encryptedClient.getKeyVault();
var keyId = keyVault.createKey("aws", masterKey, ["<Your Key Alt Name>"]);
var keyVaultClient = new MongoClient(connectionString);
var clientEncryptionOptions = new ClientEncryptionOptions(
keyVaultClient: keyVaultClient,
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders);
var clientEncryption = new ClientEncryption(clientEncryptionOptions);
var dataKeyOptions = new DataKeyOptions(
alternateKeyNames: new[] { "<Your Key Alt Name>" },
masterKey: new BsonDocument
{
{ "<Your dataKeyOpts Keys>", "<Your dataKeyOpts Values>" },
});
var dataKeyId = clientEncryption.CreateDataKey("<Your KMS Provider>", dataKeyOptions, CancellationToken.None);
clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(KeyVaultNamespace).SetKmsProviders(kmsProviders)
keyVaultClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(URI))
if err != nil {
return fmt.Errorf("Client connect error %v", err)
}
clientEnc, err := mongo.NewClientEncryption(keyVaultClient, clientEncryptionOpts)
if err != nil {
return fmt.Errorf("NewClientEncryption error %v", err)
}
defer func() {
_ = clientEnc.Close(context.TODO())
}()
masterKey := map[string]interface{}{
"<Your dataKeyOpts Key>": "<Your dataKeyOpts Value>",
}
dataKeyOpts := options.DataKey().
SetMasterKey(masterKey).
SetKeyAltNames([]string{"<Your Key Alt Name>"})
dataKeyID, err := clientEnc.CreateDataKey(context.TODO(), provider, dataKeyOpts)
if err != nil {
return fmt.Errorf("create data key error %v", err)
}
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.build())
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.build();
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
BsonDocument masterKeyProperties = new BsonDocument();
masterKeyProperties.put("provider", new BsonString("<Your KMS Provider>"));
masterKeyProperties.put("<Your dataKeyOpts Key>", new BsonString("<Your dataKeyOpts Value>"));
List keyAltNames = new ArrayList<String>();
keyAltNames.add("<Your Key Alt Name>");
BsonBinary dataKeyId = clientEncryption.createDataKey(kmsProvider, new DataKeyOptions().masterKey(masterKeyProperties).keyAltNames(keyAltNames));
const encryption = new ClientEncryption(client, {
keyVaultNamespace,
kmsProviders,
});
const masterKey = {
"<Your dataKeyOpts Key>": "<Your dataKeyOpts Value>",
};
const key = await encryption.createDataKey(provider, {
masterKey: masterKey,
keyAltNames: ["<Your Key Alt Name>"],
});
client = MongoClient(connection_string)
client_encryption = ClientEncryption(
kms_providers,
key_vault_namespace,
client,
CodecOptions(uuid_representation=STANDARD),
)
master_key={ "<Your dataKeyOpts Key>" : "<Your dataKeyOpts Value>"}
data_key_id = client_encryption.create_data_key(provider, master_key, key_alt_names=["<Your Key Alt Name>"])

要了解有关dataKeyOptskmsProviders对象的信息,请参阅KMS提供者。

加密方案包含用户指定的规则,用于标识哪些字段必须加密以及如何加密这些字段。在您的加密规则中,您可以指定用于加密字段的密钥的备用密钥名称。

您必须使用一个JSON指针来引用密钥的备用名称。JSON指针是一个以“/”字符为前缀的字符串,可以用来访问同一文档或另一个文档中的特定字段值。使用JSON指针来引用包含您的密钥备用名称值的查询或更新文档中的字段。

重要

不能为确定性加密字段使用备用名称

在加密字段时,您不能通过其备用名称引用DEK。要使用确定性加密算法加密字段,您必须指定用于加密字段的密钥的_id

考虑以下加密方案,该方案加密了salary字段

{
"<database>.<collection>": {
"bsonType": "object",
"properties": {
"salary": {
"encrypt": {
"bsonType": "int",
"keyId": "/fieldWithAltName",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
}
}
}
}
}

该方案的keyId字段包含一个JSON指针,用于引用被加密文档中的fieldWithAltName字段。

以下文档的fieldWithAltName值为my-alt-name

{
"name": "Jon Doe",
"salary": 45000,
"fieldWithAltName": "my-alt-name"
}

salary字段由具有备用名称my-alt-nameDEK加密。

您可以使用备选键名在运行时动态设置字段的加密密钥。使用此功能可以使用相同的加密模式使用不同的DEK加密单个文档。

例如,考虑以下文档

{
"name": "Jon Doe",
"salary": 45000,
"fieldWithAltName": "my-alt-name"
},
{
"name": "Jane Smith",
"salary": 70000,
"fieldWithAltName": "my-other-alt-name"
}

您使用之前示例中的加密模式配置的CSFLE启用客户端插入以下文档示例.

在加密模式中,salary.encrypt.keyId字段包含指向插入文档的fieldWithAltName字段的JSON指针。因此,两个示例文档中的salary字段都使用针对单个文档的特定DEK进行加密。密钥在运行时动态分配。

从Mongo Shell的1.5版开始,您可以使用rewrapManyDataKey方法旋转加密密钥。该rewrapManyDataKey方法自动解密多个数据密钥,并使用指定的客户主密钥重新加密它们。然后,它在密钥库集合中更新旋转后的密钥。此方法允许您根据两个可选参数旋转加密密钥

  • 用于指定要旋转的密钥的过滤器。如果没有数据密钥匹配给定的过滤器,则不会旋转任何密钥。省略过滤器以旋转密钥库集合中的所有密钥。

  • 表示新CMK的对象。省略此对象以使用当前CMK旋转数据密钥。

rewrapManyDataKey使用以下语法

keyVault = db.getKeyVault()
keyVault.rewrapManyDataKey(
{
"<Your custom filter>"
},
{
provider: "<KMS provider>",
masterKey: {
"<dataKeyOpts Key>" : "<dataKeyOpts Value>"
}
}
)

有关您的KMS提供商的dataKeyOpts对象的信息,请参阅支持的关键管理服务。

您可以使用标准CRUD 删除操作从密钥库集合中删除数据加密密钥。如果您删除了DEK,则使用该DEK加密的所有字段将永久不可读。

提示

MongoDB Shell特定功能

MongoDB Shell允许您使用UUID通过keyVault.deleteKey()方法删除DEK,如下所示

keyVault = db.getKeyVault()
keyVault.deleteKey(UUID("<UUID String>"))

有关密钥库集合的更多信息,请参阅加密密钥和密钥库。

有关如何设置支持的各种KMS提供商的CSFLE启用应用程序的教程,请参阅以下页面

要查看加密方案的更多示例,请参阅CSFLE加密方案。

返回

模式