Docs Menu
Docs Home
/ /

Utilice cifrado explícito

Esta guía le muestra cómo cifrar un documento con cifrado explícito y un controlador MongoDB.

Tras completar esta guía, podrá configurar un controlador para cifrar los campos de un documento mediante cifrado explícito. Con este conocimiento, podrá crear una aplicación cliente que utilice cifrado explícito con descifrado automático.

Importante

No utilice esta aplicación de muestra en producción

Debido a que las instrucciones de este tutorial incluyen almacenar una clave de cifrado en un entorno inseguro, no debe usar una versión no modificada de esta aplicación en producción. El uso de esta aplicación en producción acarrea el riesgo de acceso no autorizado a la llave de cifrado o la pérdida de la clave necesaria para descifrar tus datos. El propósito de este tutorial es demostrar cómo usar Queryable Encryption sin necesidad de configurar un sistema de gestión de clave.

Puede utilizar un sistema de gestión de claves para almacenar de forma segura su clave de cifrado en un entorno de producción. KMS es un servicio remoto que almacena y administra de forma segura sus claves de cifrado. Para saber cómo configurar una aplicación con cifrado consultable habilitado que utilice un KMS, consulte Tutoriales de cifrado consultable.

Para completar y ejecutar el código de esta guía, debe configurar su entorno de desarrollo como se muestra en la página Instalar un controlador compatible con cifrado consultable y dependencias.

Para ver el código completo de la aplicación de muestra, seleccione su lenguaje de programación en el selector de lenguaje.

1

Debe crear una clave maestra de cliente(CMK) para realizar el cifrado consultable.

Cree una clave maestra de cliente de 96bytes y guárdela en el archivo 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)

Advertencia

Proteja su archivo de clave local en producción

Recomendamos almacenar sus claves maestras de cliente en un sistema de gestión de claves (KMS) remoto. Para aprender a usar un KMS remoto en su implementación de cifrado consultable, consulte la guía "Tutoriales de cifrado consultable".

Si decide usar un proveedor de claves local en producción, tenga mucho cuidado y no lo almacene en el sistema de archivos. Considere inyectar la clave en su aplicación cliente mediante un proceso sidecar o utilice otro método que la mantenga segura.

Tip

Generar una CMK desde la línea de comandos

Utilice el siguiente comando para generar una CMK desde un shell de Unix o PowerShell:

  • Shell de Unix/macOS:

    echo $(head -c 96 /dev/urandom | tr -d '\n')
  • Potencia Shell:

    $r=[byte[]]::new(96);$g=[System.Security.Cryptography.RandomNumberGenerator]::Create();$g.GetBytes($r);$r

Guarde la salida del comando anterior en un archivo llamado customer-master-key.txt.

Tip

Ver: Código completo

Para ver el código completo para crear una clave maestra de cliente,consulte el repositorio de aplicaciones de muestra de cifrado consultable.

Para ver el código completo para crear una clave maestra de cliente,consulte el repositorio de aplicaciones de muestra de cifrado consultable.

Para ver el código completo para crear una clave maestra de cliente,consulte el repositorio de aplicaciones de muestra de cifrado consultable.

Para ver el código completo para crear una clave maestra de cliente,consulte el repositorio de aplicaciones de muestra de cifrado consultable.

Para ver el código completo para crear una clave maestra de cliente,consulte el repositorio de aplicaciones de muestra de cifrado consultable.

2

Cree un índice único en el campo keyAltNames en su espacio de nombres encryption.__keyVault.

Seleccione la pestaña correspondiente a su controlador MongoDB preferido:

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

Al compilar o ejecutar el código Golang de esta guía con go build o go run, incluya siempre la restricción de compilación cse para habilitar el cifrado consultable. Consulte el siguiente comando de shell para ver un ejemplo de cómo incluir la restricción de compilación:

go run -tags cse make-data-key.go
uri := "<Your MongoDB URI>"
keyVaultClient, err := mongo.Connect(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}},
)
3
  1. Lea la clave maestra del cliente y especifique la configuración del proveedor KMS

    Recupere el contenido del archivo de clave maestra del cliente que generó en el paso Crear una clave maestra del cliente de esta guía.

    Utilice el valor de CMK en la configuración de su proveedor de KMS. El cliente utiliza esta configuración para descubrir la CMK. Configure el nombre del proveedor como local para indicar que utiliza un proveedor de claves local.

    Seleccione la pestaña correspondiente a su controlador MongoDB preferido:

    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
    },
    }
  2. Crea tus claves de cifrado de datos

    Construya un cliente con su cadena de conexión MongoDB y el espacio de nombres de la colección Key Vault, y cree las claves de cifrado de datos:

    Nota

    Permisos del espacio de nombres de la colección Key Vault

    Para completar este tutorial, el usuario de la base de datos que utiliza su aplicación para conectarse a MongoDB debe tener permisos en los siguientes espacios de dbAdmin nombres:

    • 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"])
  3. Crea tu colección cifrada

    Utilice una instancia MongoClient habilitada para cifrado consultable para especificar qué campos debe cifrar y crear su colección cifrada:

    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!")

La salida del código en esta sección debería parecerse a la siguiente:

Created encrypted collection!

Tip

Ver: Código completo

Para ver el código completo para crear una llave de cifrado de datos, consulta el repositorio de apps de ejemplo de Queryable Encryption.

Para ver el código completo para crear una llave de cifrado de datos, consulta el repositorio de apps de ejemplo de Queryable Encryption.

Para ver el código completo para crear una llave de cifrado de datos, consulta el repositorio de apps de ejemplo de Queryable Encryption.

Para ver el código completo para crear una llave de cifrado de datos, consulta el repositorio de apps de ejemplo de Queryable Encryption.

Para ver el código completo para crear una llave de cifrado de datos, consulta el repositorio de apps de ejemplo de Queryable Encryption.

4
  1. Especifique el espacio de nombres de la colección Key Vault

    Especifique encryption.__keyVault como el espacio de nombres de la colección 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)
  2. Especifique la clave maestra del cliente

    Especifique el proveedor de KMS y especifique su clave maestra de cliente en línea:

    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
    },
    }
  3. Recuperar claves de cifrado de datos

    Recupere las claves de cifrado de datos creadas en el paso Crear una clave de cifrado de datos de esta guía:

    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(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"].(bson.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"].(bson.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"]
  4. Especifique la ruta de la biblioteca compartida de cifrado automático

    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>",
    )

    Tip

    Obtén más información

    Para obtener más información sobre la biblioteca a la que hace referencia esta ruta, consulte la página Biblioteca compartida de cifrado automático.

  5. Crear un objeto MongoClient

    Cree una instancia de un objeto MongoClient con las siguientes configuraciones de cifrado automático:

    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

    Nota

    Descifrado automático

    Utilizamos una instancia MongoClient con cifrado automático habilitado para realizar el descifrado automático.

    Para obtener más información sobre el cifrado explícito con descifrado automático, consulta la sección Fundamentos.

  6. Crear un objeto ClientEncryption

    Cree una instancia de un objeto ClientEncryption de la siguiente manera:

    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
    )

Nota

Algoritmos indexados y no indexados

Para obtener más información sobre los algoritmos indexados y no indexados en el cifrado explícito, consulte Elección de algoritmo.

5

Utilice su instancia MongoClient habilitada para cifrado consultable para insertar un documento con campos cifrados en el espacio de nombres medicalRecords.patients utilizando el siguiente fragmento 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,
}
)

Cuando insertas un documento, tu cliente habilitado para Queryable Encryption cifra los campos de tu documento de manera que se asemeje a lo siguiente:

{
"_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"
}
}
]
}

Advertencia

No modifique el campo __safeContent__

El campo __safeContent__ es esencial para el cifrado consultable. No modifique su contenido.

Tip

Ver: Código completo

Para ver el código completo para insertar un documento cifrado con cifrado explícito, consulta el Repositorio de la aplicación de ejemplo de Queryable Encryption.

Para ver el código completo para insertar un documento cifrado con cifrado explícito, consulta el Repositorio de la aplicación de ejemplo de Queryable Encryption.

Para ver el código completo para insertar un documento cifrado con cifrado explícito, consulta el Repositorio de la aplicación de ejemplo de Queryable Encryption.

Para ver el código completo para insertar un documento cifrado con cifrado explícito, consulta el Repositorio de la aplicación de ejemplo de Queryable Encryption.

Para ver el código completo para insertar un documento cifrado con cifrado explícito, consulta el Repositorio de la aplicación de ejemplo de Queryable Encryption.

6

Recupera el documento con campos cifrados que insertaste en el paso Insert a Document with Encrypted Fields de esta guía mediante una query en un campo cifrado:

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)

La salida del fragmento de código anterior debe contener el siguiente documento:

{
"__safeContent__": [
{
"Subtype": 0,
"Data": "LfaIuWm9o30MIGrK7GGUoStJMSNOjRgbxy5q2TPiDes="
}
],
"_id": "6303a770857952ca5e363fd2",
"firstName": "Jon",
"medications": ["Atorvastatin", "Levothyroxine"],
"patientId": 12345678
}

Tip

Ver: Código completo

Para ver el código para recuperar su documento con campos cifrados, consulte el repositorio de aplicaciones de muestra de cifrado consultable.

Para ver el código para recuperar su documento con campos cifrados, consulte el repositorio de aplicaciones de muestra de cifrado consultable.

Para ver el código para recuperar su documento con campos cifrados, consulte el repositorio de aplicaciones de muestra de cifrado consultable.

Para ver el código para recuperar su documento con campos cifrados, consulte el repositorio de aplicaciones de muestra de cifrado consultable.

Para ver el código para recuperar su documento con campos cifrados, consulte el repositorio de aplicaciones de muestra de cifrado consultable.

Para ver un tutorial sobre el uso de Queryable Encryption con un KMS remoto, consulta Tutoriales sobre Queryable Encryption.

Para aprender cómo funciona Queryable Encryption, consulta Queryable Encryption con cifrado explícito.

Para obtener más información sobre los temas mencionados en esta guía, consulte los siguientes enlaces:

Volver

Query

En esta página