使用GCP的自动客户端字段级加密
在本页中
概述
本指南向您展示如何使用Google Cloud密钥管理服务构建一个启用客户端字段级加密(CSFLE)的应用程序。
完成本指南中的步骤后,您应该有
ACMK托管在Google Cloud密钥管理服务上。
一个客户端应用程序,它使用您的CMK插入带有加密字段的文档。
开始之前
为了完成并运行本指南中的代码,您需要按照所示设置开发环境,请参阅安装要求页面。
在本指南中,代码示例使用占位文本。在运行示例之前,请将这些占位符替换为您自己的值。
例如
dek_id := "<Your Base64 DEK ID>"
您将用您的DEK ID替换双引号之间的所有内容。
dek_id := "abc123"
从右侧页面上的选择您的语言下拉菜单中选择您想要查看代码示例的编程语言。
完整应用程序代码
要查看示例应用程序的完整代码,请在语言选择器中选择您的编程语言。
设置KMS
// You are viewing the C# driver code examples. // Use the dropdown menu to select a different driver.
// You are viewing the Golang driver code examples. // Use the dropdown menu to select a different driver.
重要
当使用go build
或 go run
构建或运行本指南中的Golang代码时,始终包含 cse
构建约束以启用CSFLE。以下是一个包含构建约束的shell命令示例
go run -tags cse insert-encrypted-document.go
// You are viewing the Java synchronous driver code examples. // Use the dropdown menu to select a different driver.
// You are viewing the Node.js driver code examples. // Use the dropdown menu to select a different driver.
# You are viewing the Python driver code examples. # Use the dropdown menu to select a different driver.
注册GCP服务帐户
在 Google Cloud 上注册或登录您的现有账户
为您的项目创建服务账户
要在Google Cloud上创建服务账户,请遵循Google官方文档中的创建服务账户 指南。
添加服务账户密钥
要在Google Cloud上添加服务账户密钥,请遵循Google官方文档中的管理服务账户密钥 指南。
重要
在创建您的服务账户密钥时,您将一次性下载私钥信息。请确保以PKCS12或JSON格式下载此文件,以便在本教程的后续步骤中使用。
重要
在创建您的服务账户密钥时,您将一次性下载私钥信息。请确保以PKCS12或JSON格式下载此文件,以便在本教程的后续步骤中使用。
重要
在创建您的服务账户密钥时,您将一次性下载私钥信息。除非您使用的是附加的服务账户,否则请确保以PKCS12或JSON格式下载此文件,以便在本教程的后续步骤中使用。
重要
在创建您的服务账户密钥时,您将一次性下载私钥信息。请确保以PKCS12或JSON格式下载此文件,以便在本教程的后续步骤中使用。
重要
在创建您的服务账户密钥时,您将一次性下载私钥信息。请确保以PKCS12或JSON格式下载此文件,以便在本教程的后续步骤中使用。
创建GCP客户主密钥
创建一个新的客户主密钥
根据谷歌官方文档中的创建密钥指南,创建一个密钥环和对称密钥。
此密钥是您的客户主密钥(CMK)。
请记录以下CMK的详细信息,以用于本教程的未来步骤。
字段必需描述key_name是CMK的标识符。key_ring是密钥所属密钥组的标识符。key_version否指定密钥的版本。location是指定密钥的区域。endpoint否Google Cloud KMS的主机和可选端口。默认值为cloudkms.googleapis.com。
创建应用程序
选择与您应用程序中使用的MongoDB驱动程序相对应的选项卡,以查看相关的代码示例。
在您的密钥库集合上创建唯一索引
在您的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);
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()) }() keyVaultColl := "__keyVault" keyVaultDb := "encryption" 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) } // Drop the database storing your encrypted fields as all // the DEKs encrypting those fields were deleted in the preceding line. if err = keyVaultClient.Database("medicalRecords").Collection("patients").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 connectionString = "<Your MongoDB URI>"; String keyVaultDb = "encryption"; String keyVaultColl = "__keyVault"; String keyVaultNamespace = keyVaultDb + "." + keyVaultColl; MongoClient keyVaultClient = MongoClients.create(connectionString); // Drop the Key Vault Collection in case you created this collection // in a previous run of this application. keyVaultClient.getDatabase(keyVaultDb).getCollection(keyVaultColl).drop(); // Drop the database storing your encrypted fields as all // the DEKs encrypting those fields were deleted in the preceding line. keyVaultClient.getDatabase("medicalRecords").getCollection("patients").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 keyVaultDatabase = "encryption"; const keyVaultCollection = "__keyVault"; const keyVaultNamespace = `${keyVaultDatabase}.${keyVaultCollection}`; 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(); // Drop the database storing your encrypted fields as all // the DEKs encrypting those fields were deleted in the preceding line. await keyVaultClient.db("medicalRecords").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) # Drop the database storing your encrypted fields as all # the DEKs encrypting those fields were deleted in the preceding line. key_vault_client["medicalRecords"].drop_collection("patients") key_vault_client[key_vault_db][key_vault_coll].create_index( [("keyAltNames", ASCENDING)], unique=True, partialFilterExpression={"keyAltNames": {"$exists": True}}, )
创建数据加密密钥
添加您的GCP KMS凭证
除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>(); var provider = "gcp"; var gcpKmsOptions = new Dictionary<string, object> { { "privateKey", "<Your GCP Private Key>" }, { "email", "<Your GCP Email>" }, }; kmsProviders.Add(provider, gcpKmsOptions); 除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
provider := "gcp" kmsProviders := map[string]map[string]interface{}{ provider: { "email": "<Your GCP Email>", "privateKey": "<Your GCP Private Key>", }, } 提示
附加服务帐户
如果您正在使用附加服务帐户,您可以允许它自动将其认证到您的GCP KMS。
要自动认证,请分配一个空映射,而不是包含您的GCP凭证的映射,如下面的代码所示
String kmsProvider = "gcp"; Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>(); Map<String, Object> providerDetails = new HashMap<>(); kmsProviders.put(kmsProvider, providerDetails); 在添加此代码后,继续指南的下一步。
除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
String kmsProvider = "gcp"; Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>(); Map<String, Object> providerDetails = new HashMap<>(); providerDetails.put("email", "<Your GCP Email Address>"); providerDetails.put("privateKey", "<Your GCP Private Key>"); kmsProviders.put(kmsProvider, providerDetails); 除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
const provider = "gcp"; const kmsProviders = { gcp: { email: "<Your GCP Email>", privateKey: "<Your GCP Private Key>", }, }; 除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
provider = "gcp" kms_providers = { provider: {"email": "<your GCP email>", "privateKey": "<your GCP private key>"} } 提示
您在指南的创建GCP服务帐户步骤中保存了一个包含您的服务帐户密钥凭证的文件。
如果您以JSON格式下载了您的凭证,可以使用以下命令提取您的私钥值,将
<credentials-filename>
替换为您的凭证文件名。以下命令需要您安装OpenSSL:cat <credentials-filename> | jq -r .private_key | openssl pkcs8 -topk8 -nocrypt -inform PEM -outform DER | base64 如果您以PKCS12格式下载了您的凭证,您需要指定您的GCP服务帐户导入密码,并在使用以下命令访问时添加PEM密码短语,将
<credentials-filename>
替换为您的凭证文件名openssl pkcs12 -info -in <credentials-filename> 添加您的密钥信息
更新以下代码以指定您的客户主密钥
提示
您在本指南的创建客户主密钥步骤中记录了您的客户主密钥详细信息。
var dataKeyOptions = new DataKeyOptions( masterKey: new BsonDocument { { "projectId", "Your GCP Project ID" }, { "location", "Your GCP Key Location" } , { "keyRing", "<Your GCP Key Ring>" }, { "keyName", "<Your GCP Key Name>" }, }); masterKey := map[string]interface{}{ "projectId": "<Your GCP Project ID>", "location": "<Your GCP Location>", "keyRing": "<Your GCP Key Ring>", "keyName": "<Your GCP Key Name>", } BsonDocument masterKeyProperties = new BsonDocument(); masterKeyProperties.put("provider", new BsonString(kmsProvider)); masterKeyProperties.put("projectId", new BsonString("<Your GCP Project ID>")); masterKeyProperties.put("location", new BsonString("<Your GCP Key Location>")); masterKeyProperties.put("keyRing", new BsonString("<Your GCP Key Ring>")); masterKeyProperties.put("keyName", new BsonString("<Your GCP Key Name>")); const masterKey = { projectId: "<Your Project ID>", location: "<Your Key Location>", keyRing: "<Your Key Ring>", keyName: "<Your Key Name>", }; master_key = { "projectId": "<GCP project identifier>", "location": "<GCP region>", "keyRing": "<GCP key ring name>", "keyName": "<GCP key name>", } 生成您的数据加密密钥
使用本教程第一步中声明的变量生成您的数据加密密钥。
var clientEncryptionOptions = new ClientEncryptionOptions( keyVaultClient: keyVaultClient, keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders ); 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}"); 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()) }() dataKeyOpts := options.DataKey(). SetMasterKey(masterKey) dataKeyID, err := clientEnc.CreateDataKey(context.TODO(), provider, dataKeyOpts) if err != nil { return fmt.Errorf("create data key error %v", err) } fmt.Printf("DataKeyId [base64]: %s\n", base64.StdEncoding.EncodeToString(dataKeyID.Data)) ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString(connectionString)) .build()) .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .build(); MongoClient regularClient = MongoClients.create(connectionString); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); BsonBinary dataKeyId = clientEncryption.createDataKey(kmsProvider, new DataKeyOptions().masterKey(masterKeyProperties)); String base64DataKeyId = Base64.getEncoder().encodeToString(dataKeyId.getData()); System.out.println("DataKeyId [base64]: " + base64DataKeyId); clientEncryption.close(); const client = new MongoClient(uri); await client.connect(); const encryption = new ClientEncryption(client, { keyVaultNamespace, kmsProviders, }); const key = await encryption.createDataKey(provider, { masterKey: masterKey, }); console.log("DataKeyId [base64]: ", key.toString("base64")); await keyVaultClient.close(); await client.close(); 注意
导入ClientEncryption
当使用Node.js驱动程序v6.0及更高版本时,您必须从
mongodb
导入ClientEncryption
。对于早期版本的驱动程序,从
mongodb-client-encryption
导入ClientEncryption
。key_vault_database = "encryption" key_vault_collection = "__keyVault" key_vault_namespace = f"{key_vault_database}.{key_vault_collection}" 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 = client_encryption.create_data_key(provider, master_key) base_64_data_key_id = base64.b64encode(data_key_id) print("DataKeyId [base64]: ", base_64_data_key_id)
提示
了解更多
要查看一个说明您的客户端应用程序如何使用Google Cloud Key Management Service生成数据加密密钥的图表,请参阅架构。
要了解有关使用托管在Azure Key Vault中的客户主密钥加密数据加密密钥的选项,请参阅kmsProviders对象和dataKeyOpts对象。
提示
参见:完整代码
查看生成数据加密密钥的完整代码,请参阅我们的GitHub仓库。
查看生成数据加密密钥的完整代码,请参阅我们的GitHub仓库。
查看生成数据加密密钥的完整代码,请参阅我们的GitHub仓库。
要查看生成数据加密密钥的完整代码,请参阅我们的GitHub仓库。
要查看生成数据加密密钥的完整代码,请参阅我们的GitHub仓库。
配置MongoClient
提示
请按照本教程中的剩余步骤在之前步骤创建的单独文件中进行。
要查看此文件的完整代码,请参阅我们的Github仓库
要查看此文件的完整代码,请参阅我们的Github仓库。
要查看此文件的完整代码,请参阅我们的Github仓库。
要查看此文件的完整代码,请参阅我们的Github 仓库。
要查看此文件的完整代码,请参阅我们的Github 仓库。
指定密钥保管库集合命名空间
将
encryption.__keyVault
指定为密钥保管库集合命名空间。var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault"); keyVaultNamespace := "encryption.__keyVault" String keyVaultNamespace = "encryption.__keyVault"; const keyVaultNamespace = "encryption.__keyVault"; key_vault_namespace = "encryption.__keyVault" 指定您的云账户凭据
除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>(); var provider = "gcp"; var gcpKmsOptions = new Dictionary<string, object> { { "privateKey", "<Your GCP Private Key>" }, { "email", "<Your GCP Email>" }, }; kmsProviders.Add(provider, gcpKmsOptions); 除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
kmsProviders := map[string]map[string]interface{}{ "gcp": { "email": "<Your GCP Email>", "privateKey": "<Your GCP Private Key>", }, } 提示
附加服务帐户
如果您正在使用附加服务帐户,您可以允许它自动将其认证到您的GCP KMS。
要自动认证,请分配一个空映射,而不是包含您的GCP凭证的映射,如下面的代码所示
String kmsProvider = "gcp"; Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>(); Map<String, Object> providerDetails = new HashMap<>(); kmsProviders.put(kmsProvider, providerDetails); 在添加此代码后,继续指南的下一步。
除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
String kmsProvider = "gcp"; Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>(); Map<String, Object> providerDetails = new HashMap<>(); providerDetails.put("email", "<Your GCP Email Address>"); providerDetails.put("privateKey", "<Your GCP Private Key>"); kmsProviders.put(kmsProvider, providerDetails); 除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
const kmsProviders = { gcp: { email: "<Your GCP Email>", privateKey: "<Your GCP Private Key>", }, }; 除非您使用的是附加服务帐户,否则请将服务帐户凭证添加到您的CSFLE启用的客户端中,如下面的代码示例所示
provider = "gcp" kms_providers = { "gcp": {"email": "<your GCP email>", "privateKey": "<your GCP private key>"} } 为您的集合创建加密模式
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); dek_id := "<Your Base64 DEK ID>" schema_template := `{ "bsonType": "object", "encryptMetadata": { "keyId": [ { "$binary": { "base64": "%s", "subType": "04" } } ] }, "properties": { "insurance": { "bsonType": "object", "properties": { "policyNumber": { "encrypt": { "bsonType": "int", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } }, "medicalRecords": { "encrypt": { "bsonType": "array", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "bloodType": { "encrypt": { "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "ssn": { "encrypt": { "bsonType": "int", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } }` schema := fmt.Sprintf(schema_template, dek_id) var schemaDoc bson.Raw if err := bson.UnmarshalExtJSON([]byte(schema), true, &schemaDoc); err != nil { return fmt.Errorf("UnmarshalExtJSON error: %v", err) } schemaMap := map[string]interface{}{ dbName + "." + collName: schemaDoc, } String dekId = "<paste-base-64-encoded-data-encryption-key-id>>"; Document jsonSchema = new Document().append("bsonType", "object").append("encryptMetadata", new Document().append("keyId", new ArrayList<>((Arrays.asList(new Document().append("$binary", new Document() .append("base64", dekId) .append("subType", "04"))))))) .append("properties", new Document() .append("ssn", new Document().append("encrypt", new Document() .append("bsonType", "int") .append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"))) .append("bloodType", new Document().append("encrypt", new Document() .append("bsonType", "string") .append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random"))) .append("medicalRecords", new Document().append("encrypt", new Document() .append("bsonType", "array") .append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random"))) .append("insurance", new Document() .append("bsonType", "object") .append("properties", new Document().append("policyNumber", new Document().append("encrypt", new Document() .append("bsonType", "int") .append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic")))))); HashMap<String, BsonDocument> schemaMap = new HashMap<String, BsonDocument>(); schemaMap.put("medicalRecords.patients", BsonDocument.parse(jsonSchema.toJson())); dataKey = "<Your base64 DEK ID>"; const schema = { bsonType: "object", encryptMetadata: { keyId: [new Binary(Buffer.from(dataKey, "base64"), 4)], }, properties: { insurance: { bsonType: "object", properties: { policyNumber: { encrypt: { bsonType: "int", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", }, }, }, }, medicalRecords: { encrypt: { bsonType: "array", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", }, }, bloodType: { encrypt: { bsonType: "string", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", }, }, ssn: { encrypt: { bsonType: "int", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", }, }, }, }; var patientSchema = {}; patientSchema[namespace] = schema; dek_id = b"<paste-base-64-encoded-data-encryption-key-id>" json_schema = { "bsonType": "object", "encryptMetadata": {"keyId": [Binary(base64.b64decode(dek_id), UUID_SUBTYPE)]}, "properties": { "insurance": { "bsonType": "object", "properties": { "policyNumber": { "encrypt": { "bsonType": "int", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", } } }, }, "medicalRecords": { "encrypt": { "bsonType": "array", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", } }, "bloodType": { "encrypt": { "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", } }, "ssn": { "encrypt": { "bsonType": "int", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", } }, }, } patient_schema = {"medicalRecords.patients": json_schema} 指定自动加密共享库的位置
var mongoBinariesPath = "<Full path to your Automatic Encryption Shared Library>"; var extraOptions = new Dictionary<string, object>() { { "cryptSharedLibPath", mongoBinariesPath }, }; extraOptions := map[string]interface{}{ "cryptSharedLibPath": "<Full path to your Automatic Encryption Shared Library>", } Map<String, Object> extraOptions = new HashMap<String, Object>(); extraOptions.put("cryptSharedLibPath", "<Full path to your Automatic Encryption Shared Library>")); const extraOptions = { cryptSharedLibPath: "<Full path to your Automatic Encryption Shared Library>", }; extra_options = { "cryptSharedLibPath": "<Full path to your Automatic Encryption Shared Library>" } 创建 MongoClient
使用先前步骤中声明的变量创建具有以下自动加密设置的 MongoDB 客户端对象
MongoClientSettings.Extensions.AddAutoEncryption(); // .NET/C# Driver v3.0 or later only var clientSettings = MongoClientSettings.FromConnectionString(connectionString); var autoEncryptionOptions = new AutoEncryptionOptions( keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, schemaMap: schemaMap, extraOptions: extraOptions ); clientSettings.AutoEncryptionOptions = autoEncryptionOptions; var secureClient = new MongoClient(clientSettings); var clientSettings = MongoClientSettings.FromConnectionString(connectionString); var autoEncryptionOptions = new AutoEncryptionOptions( keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, schemaMap: schemaMap, extraOptions: extraOptions ); clientSettings.AutoEncryptionOptions = autoEncryptionOptions; var secureClient = new MongoClient(clientSettings); autoEncryptionOpts := options.AutoEncryption(). SetKmsProviders(kmsProviders). SetKeyVaultNamespace(keyVaultNamespace). SetSchemaMap(schemaMap). 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()) }() MongoClientSettings clientSettings = MongoClientSettings.builder() .applyConnectionString(new ConnectionString(connectionString)) .autoEncryptionSettings(AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .schemaMap(schemaMap) .extraOptions(extraOptions) .build()) .build(); MongoClient mongoClientSecure = MongoClients.create(clientSettings); const secureClient = new MongoClient(connectionString, { autoEncryption: { keyVaultNamespace, kmsProviders, schemaMap: patientSchema, extraOptions: extraOptions, }, }); fle_opts = AutoEncryptionOpts( kms_providers, key_vault_namespace, schema_map=patient_schema, **extra_options ) secureClient = MongoClient(connection_string, auto_encryption_opts=fle_opts)
插入带有加密字段的文档
使用您的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 client var secureCollection = secureClient.GetDatabase(db).GetCollection<BsonDocument>(coll); // Insert a document into the collection secureCollection.InsertOne(sampleDocFields);
test_patient := map[string]interface{}{ "name": "Jon Doe", "ssn": 241014209, "bloodType": "AB+", "medicalRecords": []map[string]interface{}{{ "weight": 180, "bloodPressure": "120/80", }}, "insurance": map[string]interface{}{ "provider": "MaestCare", "policyNumber": 123142, }, } if _, err := secureClient.Database(dbName).Collection(collName).InsertOne(context.TODO(), test_patient); err != nil { return fmt.Errorf("InsertOne error: %v", err) }
注意
您不必创建原始BSON文档,可以直接将带有bson
标签的结构体传递给驱动程序进行编码。
ArrayList<Document> medicalRecords = new ArrayList<>(); medicalRecords.add(new Document().append("weight", "180")); medicalRecords.add(new Document().append("bloodPressure", "120/80")); Document insurance = new Document() .append("policyNumber", 123142) .append("provider", "MaestCare"); Document patient = new Document() .append("name", "Jon Doe") .append("ssn", 241014209) .append("bloodType", "AB+") .append("medicalRecords", medicalRecords) .append("insurance", insurance); mongoClientSecure.getDatabase(recordsDb).getCollection(recordsColl).insertOne(patient);
try { const writeResult = await secureClient .db(db) .collection(coll) .insertOne({ name: "Jon Doe", ssn: 241014209, bloodType: "AB+", medicalRecords: [{ weight: 180, bloodPressure: "120/80" }], insurance: { policyNumber: 123142, provider: "MaestCare", }, }); } catch (writeError) { console.error("writeError occurred:", writeError); }
def insert_patient( collection, name, ssn, blood_type, medical_records, policy_number, provider ): insurance = {"policyNumber": policy_number, "provider": provider} doc = { "name": name, "ssn": ssn, "bloodType": blood_type, "medicalRecords": medical_records, "insurance": insurance, } collection.insert_one(doc) medical_record = [{"weight": 180, "bloodPressure": "120/80"}] insert_patient( secureClient.medicalRecords.patients, "Jon Doe", 241014209, "AB+", medical_record, 123142, "MaestCare", )
当您插入文档时,您的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存储库
要查看插入带有加密字段的文档的完整代码,请参阅我们的GitHub存储库。
要查看插入具有加密字段的文档的完整代码,请参阅我们的GitHub仓库。
要查看插入具有加密字段的文档的完整代码,请参阅我们的GitHub仓库。
要查看插入具有加密字段的文档的完整代码,请参阅我们的GitHub仓库。
使用加密字段检索您的文档
检索您在本指南的插入带加密字段的文档步骤中插入的带加密字段的文档。
为了展示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"); var ssnFilter = Builders<BsonDocument>.Filter.Eq("name", "Jon Doe"); var secureResult = secureCollection.Find(ssnFilter).Limit(1).First(); Console.WriteLine($"\n{secureResult}\n");
fmt.Println("Finding a document with regular (non-encrypted) client.") var resultRegular bson.M err = regularClient.Database(dbName).Collection(collName).FindOne(context.TODO(), bson.D{{"name", "Jon Doe"}}).Decode(&resultRegular) if err != nil { panic(err) } outputRegular, err := json.MarshalIndent(resultRegular, "", " ") if err != nil { panic(err) } fmt.Printf("%s\n", outputRegular) fmt.Println("Finding a document with encrypted client") var resultSecure bson.M err = secureClient.Database(dbName).Collection(collName).FindOne(context.TODO(), bson.D{{"name", "Jon Doe"}}).Decode(&resultSecure) if err != nil { panic(err) } outputSecure, err := json.MarshalIndent(resultSecure, "", " ") if err != nil { panic(err) } fmt.Printf("%s\n", outputSecure)
System.out.println("Finding a document with regular (non-encrypted) client."); Document docRegular = mongoClientRegular.getDatabase(recordsDb).getCollection(recordsColl).find(eq("name", "Jon Doe")).first(); System.out.println(docRegular.toJson()); System.out.println("Finding a document with encrypted client"); Document docSecure = mongoClientSecure.getDatabase(recordsDb).getCollection(recordsColl).find(eq("name", "Jon Doe")).first(); System.out.println(docSecure.toJson());
console.log("Finding a document with regular (non-encrypted) client."); console.log( await regularClient.db(db).collection(coll).findOne({ name: /Jon/ }) ); console.log("Finding a document with encrypted client"); console.log( await secureClient.db(db).collection(coll).findOne({ name: /Jon/ }) );
print("Finding a document with regular (non-encrypted) client.") result = regularClient.medicalRecords.patients.find_one({"name": "Jon Doe"}) pprint.pprint(result) print("Finding a document with encrypted client") pprint.pprint(secureClient.medicalRecords.patients.find_one({"name": "Jon Doe"}))
前面代码片段的输出应如下所示
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 { _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仓库
要查看查找具有加密字段的文档的完整代码,请参阅我们的GitHub仓库。
要查看查找具有加密字段的文档的完整代码,请参阅我们的GitHub仓库。
要查看查找具有加密字段的文档的完整代码,请参阅我们的GitHub仓库。
要查看使用加密字段的文档的完整代码,请参阅我们的Github 仓库。
了解更多
有关本指南中提到的主题的更多信息,请参阅以下链接
在参考页面了解CSFLE组件的更多信息。
在加密密钥和密钥库页面了解客户主密钥和数据加密密钥的工作原理。
在KMS提供商页面了解KMS提供商如何管理您的CSFLE密钥。