Overview
El cifrado explícito proporciona un control preciso de la seguridad, a costa de una mayor complejidad al configurar colecciones y escribir código para los controladores MongoDB. Con el cifrado explícito, se especifica cómo cifrar los campos del documento para cada operación que se realiza en la base de datos e incluye esta lógica en toda la aplicación.
El cifrado explícito está disponible en los siguientes productos MongoDB:
Servidor comunitario MongoDB
MongoDB Enterprise Advanced
MongoDB Atlas
Utilice cifrado explícito
Para utilizar el cifrado explícito, debe realizar las siguientes acciones en su aplicación habilitada para CSFLE:
Descifrar campos deforma manual o automática en sus documentos
Crear una instancia de ClientEncryption
Para utilizar el cifrado explícito, debe crear un ClientEncryption
instancia. ClientEncryption es una abstracción utilizada en todos los controladores y mongosh que encapsula la colección Key Vault y OperacionesKMS involucradas en cifrado explícito.
Para crear una instancia ClientEncryption, debe especificar la siguiente información:
Una instancia
MongoClientcon acceso a su colección de Key VaultEl espacio de nombres de su colección de Key Vault
Un
kmsProvidersobjeto configurado con acceso al proveedor KMS que aloja su clave maestra de cliente
Para más opciones ClientEncryption, consulte Opciones de MongoClient para CSFLE.
Para ver fragmentos de código que muestran cómo crear una ClientEncryption instancia, consulte la sección Ejemplo de esta guía.
Cifrar campos en operaciones de lectura y escritura
Debe actualizar las operaciones de lectura y escritura en toda su aplicación de modo que ésta encripte los campos antes de realizar operaciones de lectura y escritura.
Para cifrar campos, utilice el método encrypt de su instancia ClientEncryption.
Para ver fragmentos de código que muestran cómo utilizar el encrypt método, consulte la sección Ejemplo de esta guía.
Descifrado manual
Puede descifrar sus campos cifrados de forma manual o automática cuando utilice cifrado explícito.
Para descifrar manualmente tus campos, utiliza el método decrypt de tu instancia ClientEncryption.
Para ver fragmentos de código que muestran cómo utilizar el decrypt método, consulte la sección Ejemplo de esta guía.
Descifrado automático
Para descifrar los campos automáticamente, configurar la instancia de MongoClient de la siguiente manera:
Especifique su colección de Key Vault
Especifique un objeto
kmsProvidersSi utiliza MongoDB Community Server, configure la opción
bypassAutoEncryptionenTrue
Nota
El descifrado automático está disponible en el servidor comunitario MongoDB
Aunque el cifrado automático requiere MongoDB Enterprise o MongoDB Atlas, el descifrado automático está disponible en los siguientes productos de MongoDB:
Servidor comunitario MongoDB
MongoDB Enterprise Advanced
MongoDB Atlas
Para ver un fragmento de código que demuestra cómo habilitar el descifrado automático, seleccione la pestaña correspondiente a su idioma preferido:
var autoEncryptionOpts = { keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, bypassAutoEncryption: true, }; var encryptedClient = Mongo( connectionString, autoEncryptionOpts );
var clientSettings = MongoClientSettings.FromConnectionString(connectionString); var autoEncryptionOptions = new AutoEncryptionOptions( keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, bypassAutoEncryption: true); clientSettings.AutoEncryptionOptions = autoEncryptionOptions; var client = new MongoClient(clientSettings);
autoEncryptionOpts := options.AutoEncryption(). SetKmsProviders(kmsProviders). SetKeyVaultNamespace(KeyVaultNamespace). SetBypassAutoEncryption(true) client, 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() { _ = client.Disconnect(context.TODO()) }()
MongoClientSettings clientSettings = MongoClientSettings.builder() .applyConnectionString(new ConnectionString(connectionString)) .autoEncryptionSettings(AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders).bypassAutoEncryption(true) .build()) .build(); MongoClient mongoClient = MongoClients.create(clientSettings);
const client = new MongoClient(connectionString, { monitorCommands: true, autoEncryption: { keyVaultNamespace, kmsProviders, bypassAutoEncryption: true, }, });
auto_encryption_opts = AutoEncryptionOpts( kms_providers=kms_providers, key_vault_namespace=key_vault_namespace, bypass_auto_encryption=True, ) client = MongoClient(auto_encryption_opts=auto_encryption_opts)
Ejemplo
Supongamos que desea insertar documentos con la siguiente estructura en su instancia de MongoDB:
{ "name": "<name of person>", "age": <age of person>, "favorite-foods": ["<array of foods>"] }
Crear una instancia de MongoClient
En este ejemplo, utiliza la misma instancia MongoClient para acceder a su colección de Key Vault y para leer y escribir datos cifrados.
Los siguientes fragmentos de código muestran cómo crear una instancia MongoClient:
const autoEncryptionOpts = { keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, }; const encryptedClient = Mongo(connectionString, autoEncryptionOpts);
var client = new MongoClient(connectionString);
client, err := mongo.Connect(options.Client().ApplyURI(URI)) if err != nil { panic(fmt.Errorf("Client connect error %v", err)) }
MongoClient client = MongoClients.create(connectionString);
const client = new MongoClient(connectionString);
client = MongoClient(your_connection_uri)
Crear una instancia de ClientEncryption
Los siguientes fragmentos de código muestran cómo crear una instancia ClientEncryption:
const clientEncryption = encryptedClient.getClientEncryption();
var collection = client.GetDatabase(db).GetCollection<BsonDocument>(coll); var clientEncryptionOptions = new ClientEncryptionOptions( keyVaultClient: client, keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders); var clientEncryption = new ClientEncryption(clientEncryptionOptions);
coll := client.Database(DbName).Collection(CollName) clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(KeyVaultNamespace).SetKmsProviders(kmsProviders) clientEnc, err := mongo.NewClientEncryption(client, clientEncryptionOpts) if err != nil { panic(fmt.Errorf("NewClientEncryption error %v", err)) } defer func() { _ = clientEnc.Close(context.TODO()) }()
MongoCollection<Document> collection = client.getDatabase(db).getCollection(coll); ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString(connectionString)) .build()) .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
const collection = client.db(db).collection(coll); const encryption = new ClientEncryption(client, { keyVaultNamespace, kmsProviders, });
coll = client.employees.foods client_encryption = ClientEncryption( kms_providers, "encryption.___keyVault", client, coll.codec_options, )
Nota
Opciones de códec
El controlador Python de MongoDB requiere que especifique el CodecOptions con el que desea cifrar y descifrar sus documentos.
Especifique el CodecOptions que ha configurado en el MongoClient, Database o Collection con el que está escribiendo datos de aplicación cifrados y descifrados en MongoDB.
Cifrar campos e insertar
Desea cifrar los campos de su documento utilizando los siguientes algoritmos:
Nombre de campo | Algoritmo de cifrado | Tipo de campo BSON |
|---|---|---|
| Determinista | String |
| Sin cifrado | Int |
| Azar | Arreglo |
Los siguientes fragmentos de código muestran cómo cifrar manualmente los campos de su documento e insertarlo en MongoDB:
Nota
La dataKeyId variable en los siguientes ejemplos se refiere a una clave de cifrado de datos (DEK). Para saber cómo generar una DEK con su proveedor de claves local, consulte la Guía de inicio rápido. Para saber cómo crear una DEK con un sistema de gestión de claves específico, consulte los tutoriales de CSFLE.
const encName = clientEncryption.encrypt( dataKeyId, "Greg", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" ); const encFoods = clientEncryption.encrypt( dataKeyId, ["Cheese", "Grapes"], "AEAD_AES_256_CBC_HMAC_SHA_512-Random" ); db.getSiblingDB(database).getCollection(collection).insertOne({ name: encName, foods: encFoods, });
Nota
La dataKeyId variable en los siguientes ejemplos se refiere a una clave de cifrado de datos (DEK). Para saber cómo generar una DEK con su proveedor de claves local, consulte la Guía de inicio rápido. Para saber cómo crear una DEK con un sistema de gestión de claves específico, consulte los tutoriales de CSFLE.
var encryptedName = clientEncryption.Encrypt( "Greg", new EncryptOptions(algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", keyId: dataKeyId), CancellationToken.None); var encryptedFoods = clientEncryption.Encrypt( new BsonArray { "Cheese", "Grapes" }, new EncryptOptions(algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", keyId: dataKeyId), CancellationToken.None); collection.InsertOne(new BsonDocument { { "name", encryptedName }, { "age", 83 }, { "foods", encryptedFoods } });
Nota
La dataKeyId variable en los siguientes ejemplos se refiere a una clave de cifrado de datos (DEK). Para saber cómo generar una DEK con su proveedor de claves local, consulte la Guía de inicio rápido. Para saber cómo crear una DEK con un sistema de gestión de claves específico, consulte los tutoriales de CSFLE.
nameRawValueType, nameRawValueData, err := bson.MarshalValue("Greg") if err != nil { panic(err) } nameRawValue := bson.RawValue{Type: nameRawValueType, Value: nameRawValueData} nameEncryptionOpts := options.Encrypt(). SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"). SetKeyID(dataKeyId) nameEncryptedField, err := clientEnc.Encrypt( context.TODO(), nameRawValue, nameEncryptionOpts) if err != nil { panic(err) } foodsRawValueType, foodsRawValueData, err := bson.MarshalValue(bson.A{"Grapes", "Cheese"}) if err != nil { panic(err) } foodsRawValue := bson.RawValue{Type: foodsRawValueType, Value: foodsRawValueData} encryptionOpts := options.Encrypt(). SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Random"). SetKeyID(dataKeyId) foodsEncryptedField, err := clientEnc.Encrypt( context.TODO(), foodsRawValue, encryptionOpts) if err != nil { panic(err) } _, err = coll.InsertOne( context.TODO(), bson.D{{"name", nameEncryptedField}, {"foods", foodsEncryptedField}, {"age", 83}}) if err != nil { panic(err) }
Nota
La dataKeyId variable en los siguientes ejemplos se refiere a una clave de cifrado de datos (DEK). Para saber cómo generar una DEK con su proveedor de claves local, consulte la Guía de inicio rápido. Para saber cómo crear una DEK con un sistema de gestión de claves específico, consulte los tutoriales de CSFLE.
BsonBinary encryptedName = clientEncryption.encrypt(new BsonString("Greg"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)); BsonBinary encryptedFoods = clientEncryption.encrypt(new BsonArray().parse("[\"Grapes\", \"Foods\"]"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Random").keyId(dataKeyId)); collection.insertOne(new Document("name", encryptedName).append("foods", encryptedFoods).append("age", 83));
Nota
La dataKeyId variable en los siguientes ejemplos se refiere a una clave de cifrado de datos (DEK). Para saber cómo generar una DEK con su proveedor de claves local, consulte la Guía de inicio rápido. Para saber cómo crear una DEK con un sistema de gestión de claves específico, consulte los tutoriales de CSFLE.
encryptedName = await encryption.encrypt("Greg", { algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", keyId: dataKeyId, }); encryptedFoods = await encryption.encrypt(["Cheese", "Grapes"], { algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", keyId: dataKeyId, }); await collection.insertOne({ name: encryptedName, age: 83, foods: encryptedFoods, });
Nota
La data_key_id variable en los siguientes ejemplos se refiere a una clave de cifrado de datos (DEK). Para saber cómo generar una DEK con su proveedor de claves local, consulte la Guía de inicio rápido. Para saber cómo crear una DEK con un sistema de gestión de claves específico, consulte los tutoriales de CSFLE.
encrypted_name = client_encryption.encrypt( "Greg", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=data_key_id, ) encrypted_foods = client_encryption.encrypt( ["Cheese", "Grapes"], Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random, key_id=data_key_id, ) coll.insert_one({"name": encrypted_name, "age": 83, "foods": encrypted_foods})
Recuperar documento y descifrar campos
Los siguientes fragmentos de código muestran cómo recuperar el documento insertado y descifrar manualmente los campos cifrados:
const encNameQuery = clientEncryption.encrypt( dataKeyId, "Greg", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" ); let doc = db.getSiblingDB(database).getCollection(collection).findOne({ name: encNameQuery, }); console.log(doc); doc.name = clientEncryption.decrypt(doc.name); doc.foods = clientEncryption.decrypt(doc.foods); console.log(doc);
var nameToQuery = "Greg"; var encryptedNameToQuery = clientEncryption.Encrypt( nameToQuery, new EncryptOptions(algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", keyId: dataKeyId), CancellationToken.None); var doc = collection.Find(new BsonDocument { { "name", encryptedNameToQuery } }).Single(); Console.WriteLine($"Encrypted document: {doc}"); doc["name"] = clientEncryption.Decrypt(doc["name"].AsBsonBinaryData, CancellationToken.None); doc["foods"] = clientEncryption.Decrypt(doc["foods"].AsBsonBinaryData, CancellationToken.None); Console.WriteLine($"Decrypted field: {doc}");
nameQueryRawValueType, nameQueryRawValueData, err := bson.MarshalValue("Greg") if err != nil { panic(err) } nameQueryRawValue := bson.RawValue{Type: nameQueryRawValueType, Value: nameQueryRawValueData} nameQueryEncryptionOpts := options.Encrypt(). SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"). SetKeyID(dataKeyId) nameQueryEncryptedField, err := clientEnc.Encrypt( context.TODO(), nameQueryRawValue, nameQueryEncryptionOpts) if err != nil { panic(err) } var result bson.M err = coll.FindOne( context.TODO(), bson.D{{"name", nameQueryEncryptedField}}).Decode(&result) if err != nil { if err == mongo.ErrNoDocuments { return } panic(err) } fmt.Printf("Encrypted Document: %s\n", result) nameDecrypted, err := clientEnc.Decrypt( context.TODO(), result["name"].(bson.Binary)) foodsDecrypted, err := clientEnc.Decrypt( context.TODO(), result["foods"].(bson.Binary)) result["foods"] = foodsDecrypted result["name"] = nameDecrypted fmt.Printf("Decrypted Document: %s\n", result)
BsonBinary encryptedNameQuery = clientEncryption.encrypt(new BsonString("Greg"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)); Document result = collection.find(eq("name", encryptedNameQuery)).first(); System.out.println("Encrypted Document: " + result.toJson()); result.replace("name", clientEncryption.decrypt(new BsonBinary(result.get("name", Binary.class).getData()))); result.replace("foods", clientEncryption.decrypt(new BsonBinary(result.get("foods", Binary.class).getData()))); System.out.println("Decrypted Document: " + result.toJson());
queryEncryptedName = await encryption.encrypt("Greg", { algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", keyId: dataKeyId, }); let doc = await collection.findOne({ name: queryEncryptedName }); console.log("Encrypted Document: ", doc); doc.name = encryption.decrypt(doc.name); doc.foods = encryption.decrypt(doc.foods); console.log("Decrypted document: ", doc);
name_to_query = "Greg" encrypted_name_to_query = client_encryption.encrypt( name_to_query, Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=data_key_id, ) doc = client.employees.foods.find_one({"name": encrypted_name_to_query}) print("Encrypted document: %s" % (doc,)) doc["name"] = client_encryption.decrypt(doc["name"]) doc["foods"] = client_encryption.decrypt(doc["foods"]) print("Decrypted document: %s" % (doc,))
Aplicación del cifrado a nivel de campo del lado del servidor
MongoDB admite el uso de la validación de esquema para aplicar el cifrado de campos específicos en una colección.
Un cliente que realiza cifrado a nivel de campo del lado del cliente con el mecanismo de cifrado explícito en una instancia de MongoDB configurada para aplicar el cifrado de ciertos campos debe cifrar esos campos como se especifica en la instancia de MongoDB.
Para saber cómo configurar la aplicación de CSFLE del lado del servidor, consulte Aplicación de esquemas del lado del servidor CSFLE.
Obtén más información
Para obtener más información sobre las colecciones de Key Vault, las claves de cifrado de datos y las claves maestras de cliente, consulte Claves de cifrado y Key Vaults.
Para obtener más información sobre los proveedores de KMS y los kmsProviders objetos, consulte Proveedores de KMS.
Para ver y descargar ejemplos de código ejecutables completos para los temas tratados anteriormente, seleccione un lenguaje de programación: