Overview
Aprende cómo utilizar el mecanismo de cifrado explícito de Cifrado a Nivel de Campo en el Lado del Cliente (CSFLE).
El cifrado explícito es un mecanismo en el que se especifica cómo cifrar y descifrar campos en el documento para cada operación que se realiza en la base de datos.
El cifrado explícito está disponible en los siguientes productos MongoDB de la versión 4.2 o posteriores:
MongoDB Community Server
MongoDB Enterprise Advanced
MongoDB Atlas
Usa cifrado explícito
Para utilizar cifrado explícito, debes realizar las siguientes acciones en tu 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 KMS operaciones involucradas en el cifrado explícito.
Para crear una instancia ClientEncryption, debe especificar la siguiente información:
Una
MongoClientinstancia con acceso a tu Colección de Bóvedas de LlavesEl espacio de nombres de tu Colección de Bóvedas de Llaves
Un
kmsProvidersobjeto configurado con acceso al proveedor KMS que aloja su clave maestra de cliente
Para obtener más ClientEncryption opciones, consulte opciones específicas de CSFLE MongoClient.
Para ver fragmentos de código que muestran cómo crear una instancia de ClientEncryption, consulta la sección Ejemplo de esta guía.
Cifrar campos en operaciones de lectura y escritura
Debe actualizar las operaciones de lectura y guardado en toda su aplicación para que esta cifre los campos antes de realizar operaciones de lectura y guardado.
Para cifrar campos, utilice el método encrypt de su instancia ClientEncryption.
Para ver fragmentos de código que muestran cómo usar el método encrypt, consulte la sección Ejemplo de esta guía.
Descifrado manual
Puedes desencriptar tus campos cifrados de forma manual o automática cuando usas 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 usar el método decrypt, 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 Bóvedas de Llaves
Especifica un objeto
kmsProvidersSi utiliza MongoDB Community Server, configure la opción
bypassAutoEncryptionenTrue
Nota
El descifrado automático está disponible en MongoDB Community Server
Aunque el cifrado automático requiere MongoDB Enterprise o MongoDB Atlas, el descifrado automático está disponible en los siguientes productos de MongoDB:
MongoDB Community Server
MongoDB Enterprise Advanced
MongoDB Atlas
Para ver un snippet de código que demuestre cómo activar el descifrado automático, selecciona la pestaña correspondiente a tu lenguaje 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 deseas insertar documentos con la siguiente estructura en tu instancia de MongoDB:
{ "name": "<name of person>", "age": <age of person>, "favorite-foods": ["<array of foods>"] }
Crea una instancia de MongoClient
En este ejemplo, utilizas la misma instancia de MongoClient para acceder a tu Colección de Bóvedas de Llaves y para leer y guardar 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(context.TODO(), 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
CodecOptions
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
Quieren 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 |
| Aleatorio | Arreglo |
Los siguientes snippets de código muestran cómo cifrar manualmente los campos de tu documento e insertar tu documento en MongoDB:
Nota
La variable dataKeyId en los siguientes ejemplos se refiere a una llave de cifrado de datos (DEK). Para aprender a generar un DEK con su proveedor de llaves local, consulte la Guía de inicio rápido. Para saber cómo crear un DEK con un sistema de gestión de claves específico, consulta 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 variable dataKeyId en los siguientes ejemplos se refiere a una llave de cifrado de datos (DEK). Para aprender a generar un DEK con su proveedor de llaves local, consulte la Guía de inicio rápido. Para saber cómo crear un DEK con un sistema de gestión de claves específico, consulta 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 variable dataKeyId en los siguientes ejemplos se refiere a una llave de cifrado de datos (DEK). Para aprender a generar un DEK con su proveedor de llaves local, consulte la Guía de inicio rápido. Para saber cómo crear un DEK con un sistema de gestión de claves específico, consulta 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 variable dataKeyId en los siguientes ejemplos se refiere a una llave de cifrado de datos (DEK). Para aprender a generar un DEK con su proveedor de llaves local, consulte la Guía de inicio rápido. Para saber cómo crear un DEK con un sistema de gestión de claves específico, consulta 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 variable dataKeyId en los siguientes ejemplos se refiere a una llave de cifrado de datos (DEK). Para aprender a generar un DEK con su proveedor de llaves local, consulte la Guía de inicio rápido. Para saber cómo crear un DEK con un sistema de gestión de claves específico, consulta 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 variable data_key_id en los siguientes ejemplos se refiere a una llave de cifrado de datos (DEK). Para aprender a generar un DEK con su proveedor de llaves local, consulte la Guía de inicio rápido. Para saber cómo crear un DEK con un sistema de gestión de claves específico, consulta 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"].(primitive.Binary)) foodsDecrypted, err := clientEnc.Decrypt( context.TODO(), result["foods"].(primitive.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 de 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 realice 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 según lo especificado en la instancia de MongoDB.
Para aprender a configurar la aplicación de CSFLE del lado del servidor, consulta Aplicación del esquema del lado del servidor CSFLE.
Obtén más información
Para obtener más información sobre las Colecciones de Bóvedas de Llaves, las llaves de cifrado de datos y las llaves maestras de cliente, consulta Claves y Key Vaults.
Para obtener más información sobre KMS proveedores y kmsProviders objetos, consulta CSFLE KMS Providers.