Usar criptografia explícita
Nesta página
- Visão geral
- Antes de começar
- Código completo do aplicativo
- Procedimento
- Criar uma chave mestra do cliente
- Crie um índice único em sua coleção do Key Vault
- Crie seu diretório de dados e collection criptografada
- Configure seu MongoClient para leituras e gravações criptografadas
- Inserir um documento com campos criptografados
- Recupere seu documento com campos criptografados
- Saiba mais
Visão geral
Este guia mostra como criptografar um documento com criptografia explícita e um driver MongoDB.
Após concluir este guia, você poderá configurar um driver para criptografar campos em um documento usando criptografia explícita. Com esse conhecimento, você deve ser capaz de criar um aplicativo cliente que use criptografia explícita. com descriptografia automática.
Importante
Não use este aplicativo de amostra em produção
Como as instruções deste tutorial incluem o armazenamento de uma chave de criptografia em um ambiente inseguro, você não deve usar uma versão não modificada desse aplicativo em produção. O uso desse aplicativo em produção está sujeito ao acesso não autorizado à chave de criptografia ou à perda da chave necessária para descriptografar seus dados. O objetivo deste tutorial é demonstrar como usar a Queryable Encryption sem precisar configurar um Sistema de Gerenciamento de Chaves.
Você pode usar um sistema de gerenciamento de chaves para armazenar com segurança sua chave de criptografia em um ambiente de produção. Um KMS é um serviço remoto que armazena e gerencia com segurança suas chaves de encriptação. Para saber como configurar um aplicação habilitado para Queryable Encryption que usa um KMS, consulte os Tutoriais de Queryable Encryption .
Antes de começar
Para concluir e executar o código neste guia, você precisa configurar seu ambiente de desenvolvimento, conforme mostrado na página Instalar um driver compatível Queryable Encryption .
Código completo do aplicativo
Para ver o código completo do aplicação de amostra , selecione sua linguagem de programação no seletor de idioma.
Procedimento
Criar uma chave mestra do cliente
Você deve criar uma chave mestra do cliente (CMK) para executar a Queryable Encryption.
Crie uma chave mestra do cliente de 96 bytes e salve-a no arquivo master-key.txt
:
using (var randomNumberGenerator = System.Security.Cryptography.RandomNumberGenerator.Create()) { var bytes = new byte[96]; randomNumberGenerator.GetBytes(bytes); var localMasterKeyBase64Write = Convert.ToBase64String(bytes); File.WriteAllText("master-key.txt", localMasterKeyBase64Write); }
func localMasterKey() []byte { key := make([]byte, 96) if _, err := rand.Read(key); err != nil { log.Fatalf("Unable to create a random 96 byte data key: %v", err) } if err := ioutil.WriteFile("master-key.txt", key, 0644); err != nil { log.Fatalf("Unable to write key to file: %v", err) } return key }
byte[] localMasterKeyWrite = new byte[96]; new SecureRandom().nextBytes(localMasterKeyWrite); try (FileOutputStream stream = new FileOutputStream("master-key.txt")) { stream.write(localMasterKeyWrite); }
const fs = require("fs"); const crypto = require("crypto"); try { fs.writeFileSync("master-key.txt", crypto.randomBytes(96)); } catch (err) { console.error(err); }
path = "master-key.txt" file_bytes = os.urandom(96) with open(path, "wb") as f: f.write(file_bytes)
Aviso
Proteja seu arquivo de chave local em produção
Recomendamos armazenar as chaves mestras do cliente em um sistema de gerenciamento de chaves remoto (KMS ). Para saber como usar um KMS remoto na implementação do Queryable Encryption , consulte o guia Tutoriais .
Se você optar por usar um provedor de chaves local em produção, tenha muito cuidado e não o armazene no sistema de arquivos. Considere injetar a chave em seu aplicação cliente usando um processo secundário ou use outra abordagem que mantenha a chave segura.
Dica
Gere uma chave mestra do cliente a partir da linha de comando
Use o seguinte comando para gerar uma chave mestra do cliente a partir de um shell Unix ou PowerShell:
Shell Unix:
echo $(head -c 96 /dev/urandom | base64 | tr -d '\n') PowerShell:
$r=[byte[]]::new(64);$g=[System.Security.Cryptography.RandomNumberGenerator]::Create();$g.GetBytes($r);[Convert]::ToBase64String($r)
Salve a saída do comando anterior em um arquivo denominado customer-master-key.txt
.
Dica
Veja: Código Completo
Para ver o código completo para criar uma chave mestra do cliente, consulte o repositório do aplicação de exemplo do Queryable Encryption .
Para ver o código completo para criar uma chave mestra do cliente, consulte o repositório do aplicação de exemplo do Queryable Encryption .
Para ver o código completo para criar uma chave mestra do cliente, consulte o repositório do aplicação de exemplo do Queryable Encryption .
Para ver o código completo para criar uma chave mestra do cliente, consulte o repositório do aplicação de exemplo do Queryable Encryption .
Para ver o código completo para criar uma chave mestra do cliente, consulte o repositório do aplicação de exemplo do Queryable Encryption .
Crie um índice único em sua coleção do Key Vault
Crie um índice único no campo keyAltNames
no seu espaço de nomes encryption.__keyVault
.
Selecione a guia correspondente ao driver MongoDB de sua preferência:
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);
Importante
Ao criar ou executar o código Go neste guia usando go build
ou go run
, sempre inclua a restrição de compilação cse
para ativar a Queryable Encryption. Consulte o seguinte comando shell para obter um exemplo de inclusão da restrição de compilação:
go run -tags cse make-data-key.go
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}}, )
Crie seu diretório de dados e collection criptografada
Leia a chave mestre do cliente e especifique as configurações do provedor KMS
Recupere o conteúdo do arquivo de chave mestra do cliente que você gerou na etapa Criar uma chave mestra do cliente deste guia.
Use o valor CMK nas configurações do provedor KMS. O cliente usa essas configurações para descobrir a CMK. Defina o nome do provedor como
local
para indicar que você está usando um provedor de chaves local.Selecione a guia correspondente ao driver MongoDB de sua preferência:
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 }, } Crie seu diretório de dados
Crie um cliente com sua connection string do MongoDB e o namespace da collection do Key Vault e crie as chaves de criptografia de dados:
Observação
Permissões de namespace da coleção de cofre de chaves
Para concluir este tutorial, o usuário do banco de dados que seu aplicativo usa para se conectar ao MongoDB deve ter permissões
dbAdmin
nos seguintes namespaces:encryption.__keyVault
medicalRecords
database
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"]) Crie sua coleção criptografada
Use uma instância
MongoClient
habilitada para Queryable Encryption para especificar quais campo você deve criptografar e criar sua collection criptografada: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, 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!")
A saída do código nesta seção deve se assemelhar ao seguinte:
Created encrypted collection!
Dica
Veja: Código Completo
Para exibir o código completo para criar uma Chave de criptografia de dados,consulte o repositório do aplicativo de amostra do Queryable Encryption.
Para exibir o código completo para criar uma Chave de criptografia de dados,consulte o repositório do aplicativo de amostra do Queryable Encryption.
Para exibir o código completo para criar uma Chave de criptografia de dados,consulte o repositório do aplicativo de amostra do Queryable Encryption.
Para exibir o código completo para criar uma Chave de criptografia de dados,consulte o repositório do aplicativo de amostra do Queryable Encryption.
Para exibir o código completo para criar uma Chave de criptografia de dados,consulte o repositório do aplicativo de amostra do Queryable Encryption.
Configure seu MongoClient para leituras e gravações criptografadas
Especifique o namespace da coleção do Key Vault
Especifique
encryption.__keyVault
como o namespace da coleção Key Vault.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) Especificar a chave mestre do cliente
Especifique o fornecedor de KMS e especifique a chave mestra do cliente em linha:
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 }, } Recuperar chaves de criptografia de dados
Recupere as chaves de criptografia de dados criadas na etapa Criar uma chave de criptografia de dados deste guia:
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"] Especifique o caminho da biblioteca compartilhada de criptografia automática
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>", ) Dica
Saiba mais
Para saber mais sobre a biblioteca referenciada por esse caminho, consulte a página Biblioteca compartilhada de criptografia automática .
Criar um objeto MongoClient
Instancie um objeto
MongoClient
com as seguintes configurações de criptografia automática: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 Observação
Descriptografia automática
Usamos uma instância
MongoClient
com criptografia automática habilitada para realizar a descriptografia automática.Para saber mais sobre criptografia explícita com descriptografia automática, consulte a seção Noções básicas.
Criar um objeto ClientEncryption
Instancie um objeto
ClientEncryption
da seguinte maneira: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 )
Observação
Algoritmos Indexados e Não Indexados
Para saber mais sobre os algoritmos indexados e não indexados na criptografia explícita, consulte Escolha do algoritmo.
Inserir um documento com campos criptografados
Use sua instância MongoClient
habilitada para Queryable Encryption para inserir um documento com campos criptografados no namespace medicalRecords.patients
usando o seguinte trecho de código:
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: 8), 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(8) 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(8L)); 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: 8, }); 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=8 ) 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, } )
Quando você insere um documento, o cliente habilitado para Queryable Encryption criptografa os campos do documento de forma que ele se pareça com o seguinte:
{ "_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" } } ] }
Aviso
Não modifique o campo __safeContent__.
O campo __safeContent__
é essencial para o Queryable Encryption. Não modifique o conteúdo deste campo.
Dica
Veja: Código Completo
Para exibir o código completo para inserir um documento criptografado com criptografia explícita, consulte o repositório do aplicativo de amostra do Queryable Encryption.
Para exibir o código completo para inserir um documento criptografado com criptografia explícita, consulte o repositório do aplicativo de amostra do Queryable Encryption.
Para exibir o código completo para inserir um documento criptografado com criptografia explícita, consulte o repositório do aplicativo de amostra do Queryable Encryption.
Para exibir o código completo para inserir um documento criptografado com criptografia explícita, consulte o repositório do aplicativo de amostra do Queryable Encryption.
Recupere seu documento com campos criptografados
Recupere o documento com campos criptografados inseridos na etapa Inserir um documento com campos criptografados deste guia por meio de uma query em um campo criptografado:
var findPayload = clientEncryption.Encrypt( patientId, new EncryptOptions(algorithm: "Indexed", keyId: dataKeyId1, queryType: "equality", contentionFactor: 8), 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(8) 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(8L)); 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: 8, }); console.log("Finding a document with manually encrypted field:"); console.log(await encryptedColl.findOne({ patientId: findPayload }));
find_payload = client_encryption.encrypt( patientId, Algorithm.INDEXED, data_key_id_1, query_type=QueryType.EQUALITY, contention_factor=8, ) doc = coll.find_one({"encryptedIndexed": find_payload}) print("\nReturned document:\n") pprint.pprint(doc)
A saída do trecho de código anterior deve conter o seguinte documento:
{ "__safeContent__": [ { "Subtype": 0, "Data": "LfaIuWm9o30MIGrK7GGUoStJMSNOjRgbxy5q2TPiDes=" } ], "_id": "6303a770857952ca5e363fd2", "firstName": "Jon", "medications": ["Atorvastatin", "Levothyroxine"], "patientId": 12345678 }
Dica
Veja: Código Completo
Para exibir o código para recuperar seu documento com campos criptografados, consulte o repositório do aplicação de amostra do Queryable Encryption .
Para exibir o código para recuperar seu documento com campos criptografados, consulte o repositório do aplicação de amostra do Queryable Encryption .
Para exibir o código para recuperar seu documento com campos criptografados, consulte o repositório do aplicação de amostra do Queryable Encryption .
Para exibir o código para recuperar seu documento com campos criptografados, consulte o repositório do aplicação de amostra do Queryable Encryption .
Para exibir o código para recuperar seu documento com campos criptografados, consulte o repositório do aplicação de amostra do Queryable Encryption .
Saiba mais
Para ver um tutorial sobre como usar o Queryable Encryption com um KMS remoto, consulte Tutoriais.
Para saber como funciona a Queryable Encryption, consulte criptografia explícita.
Para saber mais sobre os tópicos mencionados neste guia, consulte os seguintes links: