对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

通过 KMIP 使用客户端字段级自动加密

本指南介绍如何使用符合 Key Management Interoperability Protocol (KMIP) 的提供商来构建支持客户端字段级加密 (CSFLE) 的应用程序。

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

  • 在KMIP兼容密钥提供程序上托管的客户主密钥。

  • 正常工作的客户端应用程序;可以使用客户主密钥插入具有加密字段的文档。

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

在本指南中,代码示例使用占位符文本。在运行示例之前,请用您自己的值替换这些占位符。

例如:

dek_id := "<Your Base64 DEK ID>"

您可以将引号之间的内容替换为您的 DEK ID。

dek_id := "abc123"

从页面右侧的 Select your language 下拉菜单中选择您想要查看其代码示例的编程语言。

提示

请参阅:完整应用程序

要查看本教程的完整可运行应用程序代码,请访问以下链接:

注意

mongod 初创企业读取 KMIP 配置。默认情况下,服务器使用 KMIP 协议版本 1.2。

要连接到版本 1.0 或 1.1 的 KMIP 服务器,请使用useLegacyProtocol设置。

// You are viewing the .NET/C# driver code examples.// Use the dropdown menu to select a different driver.
1

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

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

2

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

var tlsOptions = new Dictionary<string, SslSettings>();var sslSettings = new SslSettings();var clientCertificate = new X509Certificate2("<path to your pkcs12 client certificate file>");sslSettings.ClientCertificates = new List<X509Certificate>() { clientCertificate, };tlsOptions.Add(provider, sslSettings);

重要

客户端证书必须采用 pkcs12 格式。您可以通过以下命令使用OpenSSL转换证书:

openssl pkcs12 -export -out "<new pkcs12 certificate>" -in "<certificate to convert>" \-name "<new certificate name>" -password "<new certificate password>"

选择与您在应用程序中使用的 MongoDB 驱动程序相对应的标签页,查看相关代码示例。

1

在 encryption.__keyVault 命名空间中的 keyAltNames 字段上创建唯一索引。

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

var connectionString = "<Your MongoDB URI>";var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");var keyVaultClient = new MongoClient(connectionString);var indexOptions = new CreateIndexOptions<BsonDocument>();indexOptions.Unique = true;indexOptions.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.ToString());// Drop the Key Vault Collection in case you created this collection// in a previous run of this application. keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);// Drop the database storing your encrypted fields as all// the DEKs encrypting those fields were deleted in the preceding line.keyVaultClient.GetDatabase("medicalRecords").DropCollection("patients");var keyVaultCollection = keyVaultDatabase.GetCollection<BsonDocument>(keyVaultNamespace.CollectionName.ToString());keyVaultCollection.Indexes.CreateOne(indexModel);
2

指定符合KMIP的密钥提供商的 URI 端点:

var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();var provider = "kmip";var kmipKmsOptions = new Dictionary<string, object>{ { "endpoint", "<endpoint for your KMIP-compliant key provider>" },};kmsProviders.Add(provider, kmipKmsOptions);

以下代码会提示符合KMIP的密钥提供商自动生成客户主密钥:

var dataKeyOptions = new DataKeyOptions( masterKey: new BsonDocument { } // an empty key object prompts your KMIP-compliant key provider to generate a new Customer Master Key);

使用本教程的步骤 1 中声明的变量,生成数据加密密钥。

var clientEncryptionOptions = new ClientEncryptionOptions( keyVaultClient: keyVaultClient, keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, tlsOptions: tlsOptions ); var clientEncryption = new ClientEncryption(clientEncryptionOptions);var dataKeyId = clientEncryption.CreateDataKey(provider, dataKeyOptions, CancellationToken.None);var dataKeyIdBase64 = Convert.ToBase64String(GuidConverter.ToBytes(dataKeyId, GuidRepresentation.Standard));Console.WriteLine($"DataKeyId [base64]: {dataKeyIdBase64}");

提示

请参阅:完整代码

要查看制作数据加密密钥的完整代码,请参阅我们的 Github 存储库。

3

提示

在与前面步骤中创建的文件不同的单独文件中,执行本教程中的其余步骤。

要查看该文件的完整代码,请参阅我们的 Github 存储库

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

var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");

在kmsProviders对象中指定kmip ,并输入KMIP兼容提供商的 URI 端点:

var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();var provider = "kmip";var kmipKmsOptions = new Dictionary<string, object>{ { "endpoint", "<endpoint for your KMIP-compliant key provider>" },};kmsProviders.Add(provider, kmipKmsOptions);

创建加密模式,指定客户端应用程序加密文档字段的方式:

提示

添加数据加密密钥 Base64 ID

请务必更新以下代码以包含 Base64 DEK ID。您在本指南的生成数据加密密钥步骤中获得了该值。

var keyId = "<Your base64 DEK ID here>";var schema = new BsonDocument{ { "bsonType", "object" }, { "encryptMetadata", new BsonDocument("keyId", new BsonArray(new[] { new BsonBinaryData(Convert.FromBase64String(keyId), BsonBinarySubType.UuidStandard) })) }, { "properties", new BsonDocument { { "ssn", new BsonDocument { { "encrypt", new BsonDocument { { "bsonType", "int" }, { "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } } }, { "bloodType", new BsonDocument { { "encrypt", new BsonDocument { { "bsonType", "string" }, { "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } } } }, { "medicalRecords", new BsonDocument { { "encrypt", new BsonDocument { { "bsonType", "array" }, { "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } } } }, { "insurance", new BsonDocument { { "bsonType", "object" }, { "properties", new BsonDocument { { "policyNumber", new BsonDocument { { "encrypt", new BsonDocument { { "bsonType", "int" }, { "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } } } } } } } } }};var schemaMap = new Dictionary<string, BsonDocument>();schemaMap.Add(dbNamespace, schema);

提示

关于模式的进一步阅读

要查看有关如何构建在此步骤中使用的模式的深入说明,请参阅加密模式指南。

要查看加密模式支持的所有加密规则列表,请参阅CSFLE 加密模式指南。

var mongoBinariesPath = "<Full path to your Automatic Encryption Shared Library>";var extraOptions = new Dictionary<string, object>(){ { "cryptSharedLibPath", mongoBinariesPath },};

注意

自动加密选项

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

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

使用以下自动加密设置实例化 MongoDB 客户端对象,这些设置使用前面步骤中声明的变量:

var clientSettings = MongoClientSettings.FromConnectionString(connectionString);var autoEncryptionOptions = new AutoEncryptionOptions( keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, schemaMap: schemaMap, extraOptions: extraOptions, tlsOptions: tlsOptions );clientSettings.AutoEncryptionOptions = autoEncryptionOptions;var secureClient = new MongoClient(clientSettings);
4

使用启用了 CSFLE 的 MongoClient 实例,通过以下代码片段将具有加密字段的文档插入到 medicalRecords.patients 命名空间中:

var sampleDocFields = new BsonDocument{ { "name", "Jon Doe" }, { "ssn", 145014000 }, { "bloodType", "AB-" }, { "medicalRecords", new BsonArray { new BsonDocument("weight", 180), new BsonDocument("bloodPressure", "120/80") } }, { "insurance", new BsonDocument { { "policyNumber", 123142 }, { "provider", "MaestCare" } } }}; // Construct an auto-encrypting clientvar secureCollection = secureClient.GetDatabase(db).GetCollection<BsonDocument>(coll); // Insert a document into the collectionsecureCollection.InsertOne(sampleDocFields);

在您插入文档时,启用了 CSFLE 的客户端对文档字段进行加密,以使其类似于以下内容:

{ "_id": { "$oid": "<_id of your document>" }, "name": "Jon Doe", "ssn": { "$binary": "<cipher-text>", "$type": "6" }, "bloodType": { "$binary": "<cipher-text>", "$type": "6" }, "medicalRecords": { "$binary": "<cipher-text>", "$type": "6" }, "insurance": { "provider": "MaestCare", "policyNumber": { "$binary": "<cipher-text>", "$type": "6" } }}

提示

请参阅:完整代码

要查看用于插入带加密字段的文档的完整代码,请访问我们的 Github 存储库

5

检索您在本指南的插入具有加密字段的文档步骤中插入的具有加密字段的文档。

为了显示 CSFLE 的功能,以下代码片段使用配置为自动 CSFLE 的客户端以及未配置为自动 CSFLE 的客户端来查询文档。

Console.WriteLine("Finding a document with regular (non-encrypted) client.");var filter = Builders<BsonDocument>.Filter.Eq("name", "Jon Doe");var regularResult = regularCollection.Find(filter).Limit(1).ToList()[0];Console.WriteLine($"\n{regularResult}\n"); Console.WriteLine("Finding a document with encrypted client, searching on an encrypted field");var ssnFilter = Builders<BsonDocument>.Filter.Eq("ssn", 145014000);var secureResult = secureCollection.Find(ssnFilter).Limit(1).First();Console.WriteLine($"\n{secureResult}\n");

上述代码片段的输出应如下所示:

Finding a document with regular (non-encrypted) client. { _id: new ObjectId("629a452e0861b3130887103a"), name: 'Jon Doe', ssn: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e7910c20697e5f4fa95710aafc9153f0a3dc769c8a132a604b468732ff1f4d8349ded3244b59cbfb41444a210f28b21ea1b6c737508d9d30e8baa30c1d8070c4d5e26", "hex"), 6), bloodType: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e79022e238536dfd8caadb4d7751ac940e0f195addd7e5c67b61022d02faa90283ab69e02303c7e4001d1996128428bf037dea8bbf59fbb20c583cbcff2bf3e2519b4", "hex"), 6), 'key-id': 'demo-data-key', medicalRecords: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e790405163a3207cff175455106f57eef14e5610c49a99bcbd14a7db9c5284e45e3ee30c149354015f941440bf54725d6492fb3b8704bc7c411cff6c868e4e13c58233c3d5ed9593eca4e4d027d76d3705b6d1f3b3c9e2ceee195fd944b553eb27eee69e5e67c338f146f8445995664980bf0", "hex"), 6), insurance: { policyNumber: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e79108decd85c05be3fec099e015f9d26d9234605dc959cc1a19b63072f7ffda99db38c7b487de0572a03b2139ac3ee163bcc40c8508f366ce92a5dd36e38b3c742f7", "hex"), 6), provider: 'MaestCare' }} Finding a document with encrypted client, searching on an encrypted field { _id: new ObjectId("629a452e0861b3130887103a"), name: 'Jon Doe', ssn: 241014209, bloodType: 'AB+', 'key-id': 'demo-data-key', medicalRecords: [ { weight: 180, bloodPressure: '120/80' } ], insurance: { policyNumber: 123142, provider: 'MaestCare' }}

提示

请参阅:完整代码

要查看用于插入带加密字段的文档的完整代码,请访问我们的 Github 存储库

要学习;了解CSFLE 的工作原理,请参阅 CSFLE 基础知识。

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

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

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

  • 在 CSFLE KMS 提供者页面上了解 KMS 提供者如何管理您的 CSFLE 密钥。