A partir de la versión4.2 7600, MongoDB admite el cifrado del lado del cliente. Este cifrado permite a administradores y desarrolladores cifrar campos de datos específicos, además de ofrecer otras funciones de cifrado de MongoDB.
Con el cifrado a nivel de campo, los desarrolladores pueden cifrar campos en el lado del cliente sin necesidad de configuración ni directivas del lado del servidor. El cifrado a nivel de campo del lado del cliente es compatible con cargas de trabajo donde las aplicaciones deben garantizar que terceros no autorizados, incluidos los administradores del servidor, no puedan leer los datos cifrados.
Importante
Esta guía utiliza el Subscriber implementaciones, que se describen en el Manual de inicio rápido.
Instalación
La forma recomendada de empezar a usar el cifrado a nivel de campo en su proyecto es mediante un sistema de gestión de dependencias. El cifrado a nivel de campo requiere paquetes adicionales además del controlador.
Nota
Para obtener instrucciones sobre cómo instalar el controlador Java Reactive Streams, consulte la guía de instalación.
libmongocrypt
Hay un archivo JAR separado que contiene enlaces libmongocrypt.
Si estás usando MavenPara administrar sus paquetes, agregue la siguiente entrada a su pom.xml lista de dependencias:
<dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-crypt</artifactId> <version>1.2.1</version> </dependency> </dependencies>
Si utiliza Gradle para administrar sus paquetes, agregue la siguiente entrada a su lista de dependencias:
dependencies { implementation 'org.mongodb:mongodb-crypt:1.2.1' }
Configuración de mongocryptd
Los enlaces libmongocrypt requieren que el demonio/proceso mongocryptd esté en ejecución. Se puede configurar una URI específica para el demonio/proceso en la clase AutoEncryptionSettings configurando mongocryptdURI en la configuración extraOptions.
Ejemplos
El siguiente ejemplo es una aplicación de ejemplo que asume que la clave y el esquema ya se crearon en MongoDB. El ejemplo usa una clave local, pero también puede usar el Servicio de Administración de Claves de AWS/Azure/GCP. Los datos del campo encryptedField se cifran automáticamente al insertar y se descifran al usar la función de búsqueda en el cliente.
El ejemplo de código proviene del archivo ClientSideEncryptionSimpleTour.java en el repositorio de código fuente del controlador de GitHub.
import com.mongodb.AutoEncryptionSettings; import com.mongodb.MongoClientSettings; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; import com.mongodb.reactivestreams.client.MongoCollection; import org.bson.Document; import java.security.SecureRandom; import java.util.HashMap; import java.util.Map; public class ClientSideEncryptionSimpleTour { public static void main(final String[] args) { // This would have to be the same master key as was used to create the encryption key final byte[] localMasterKey = new byte[96]; new SecureRandom().nextBytes(localMasterKey); Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>() {{ put("local", new HashMap<String, Object>() {{ put("key", localMasterKey); }}); }}; String keyVaultNamespace = "admin.datakeys"; AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .build(); MongoClientSettings clientSettings = MongoClientSettings.builder() .autoEncryptionSettings(autoEncryptionSettings) .build(); MongoClient mongoClient = MongoClients.create(clientSettings); MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("coll"); ObservableSubscriber<Void> successSubscriber = new OperationSubscriber<>(); collection.drop().subscribe(successSubscriber); successSubscriber.await(); successSubscriber = new OperationSubscriber<>(); collection.insertOne(new Document("encryptedField", "123456789")).subscribe(successSubscriber); successSubscriber.await(); ObservableSubscriber<Document> documentSubscriber = new PrintDocumentSubscriber(); collection.find().first().subscribe(documentSubscriber); documentSubscriber.await(); } }
Nota
El cifrado automático es una función exclusiva de las empresas.
El siguiente ejemplo muestra cómo configurar la instancia AutoEncryptionSettings para crear una nueva clave y establecer el mapa de esquema JSON.
El ejemplo de código proviene del archivo ClientSideEncryptionAutoEncryptionSettingsTour.java en el repositorio de código fuente del controlador de GitHub.
import com.mongodb.ClientEncryptionSettings; import com.mongodb.ConnectionString; import com.mongodb.client.model.vault.DataKeyOptions; import com.mongodb.client.vault.ClientEncryption; import com.mongodb.client.vault.ClientEncryptions; import org.bson.BsonBinary; import org.bson.BsonDocument; import java.util.Base64; ... String keyVaultNamespace = "admin.datakeys"; ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://localhost")) .build()) .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); BsonBinary dataKeyId = clientEncryption.createDataKey("local", new DataKeyOptions()); final String base64DataKeyId = Base64.getEncoder().encodeToString(dataKeyId.getData()); final String dbName = "test"; final String collName = "coll"; AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .schemaMap(new HashMap<String, BsonDocument>() {{ put(dbName + "." + collName, // Need a schema that references the new data key BsonDocument.parse("{" + " properties: {" + " encryptedField: {" + " encrypt: {" + " keyId: [{" + " \"$binary\": {" + " \"base64\": \"" + base64DataKeyId + "\"," + " \"subType\": \"04\"" + " }" + " }]," + " bsonType: \"string\"," + " algorithm: \"AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic\"" + " }" + " }" + " }," + " \"bsonType\": \"object\"" + "}")); }}).build();
Cifrado y descifrado explícitos
El cifrado y descifrado explícitos es una función de la comunidad de MongoDB y no utiliza el proceso mongocryptd. El cifrado explícito lo proporciona la clase ClientEncryption.
El ejemplo de código proviene del archivo ClientSideEncryptionExplicitEncryptionAndDecryptionTour.java en el repositorio de código fuente del controlador de GitHub.
// This would have to be the same master key as was used to create the encryption key final byte[] localMasterKey = new byte[96]; new SecureRandom().nextBytes(localMasterKey); Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>() {{ put("local", new HashMap<String, Object>() {{ put("key", localMasterKey); }}); }}; MongoNamespace keyVaultNamespace = new MongoNamespace("encryption.testKeyVault"); MongoClientSettings clientSettings = MongoClientSettings.builder().build(); MongoClient mongoClient = MongoClients.create(clientSettings); // Set up the key vault for this example MongoCollection<Document> keyVaultCollection = mongoClient .getDatabase(keyVaultNamespace.getDatabaseName()) .getCollection(keyVaultNamespace.getCollectionName()); ObservableSubscriber<Void> successSubscriber = new OperationSubscriber<>(); keyVaultCollection.drop().subscribe(successSubscriber); successSubscriber.await(); // Ensure that two data keys cannot share the same keyAltName. ObservableSubscriber<String> indexSubscriber = new OperationSubscriber<>(); keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"), new IndexOptions().unique(true) .partialFilterExpression(Filters.exists("keyAltNames"))) .subscribe(indexSubscriber); indexSubscriber.await(); MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("coll"); successSubscriber = new OperationSubscriber<>(); collection.drop().subscribe(successSubscriber); successSubscriber.await(); // Create the ClientEncryption instance ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://localhost")) .build()) .keyVaultNamespace(keyVaultNamespace.getFullName()) .kmsProviders(kmsProviders) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); BsonBinary dataKeyId = clientEncryption.createDataKey("local", new DataKeyOptions()); // Explicitly encrypt a field BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)); ObservableSubscriber<InsertOneResult> insertOneSubscriber = new OperationSubscriber<>(); collection.insertOne(new Document("encryptedField", encryptedFieldValue)) .subscribe(insertOneSubscriber); insertOneSubscriber.await(); ObservableSubscriber<Document> documentSubscriber = new OperationSubscriber<>(); collection.find().first().subscribe(documentSubscriber); Document doc = documentSubscriber.get().get(0); System.out.println(doc.toJson()); // Explicitly decrypt the field System.out.println( clientEncryption.decrypt(new BsonBinary(doc.get("encryptedField", Binary.class).getData())) );
Cifrado explícito y descifrado automático
Aunque el cifrado automático requiere MongoDB 4.2 Enterprise o un clúster MongoDB 4.2 Atlas, el descifrado automático es compatible con todos los usuarios. Para configurar el descifrado automático sin cifrado automático, configure bypassAutoEncryption(true).
El ejemplo de código proviene del archivo ClientSideEncryptionExplicitEncryptionOnlyTour.java en el repositorio de código fuente del controlador de GitHub.
... MongoClientSettings clientSettings = MongoClientSettings.builder() .autoEncryptionSettings(AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace.getFullName()) .kmsProviders(kmsProviders) .bypassAutoEncryption(true) .build()) .build(); MongoClient mongoClient = MongoClients.create(clientSettings); ... // Explicitly encrypt a field BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)); ObservableSubscriber<InsertOneResult> insertOneSubscriber = new OperationSubscriber<>(); collection.insertOne(new Document("encryptedField", encryptedFieldValue)) .subscribe(insertOneSubscriber); insertOneSubscriber.await(); ObservableSubscriber<Document> documentSubscriber = new OperationSubscriber<>(); collection.find().first().subscribe(documentSubscriber); Document doc = documentSubscriber.get().get(0); System.out.println(doc.toJson());