La aplicación de muestra Crypto Shredding demuestra cómo puedes hacer uso de los MongoDB's Cifrado a nivel de campo del lado del cliente (CSFLE) para fortalecer los procedimientos de eliminación de datos confidenciales.
Acerca de la aplicación de muestra
El derecho de supresión, también conocido como el derecho al olvido, es un derecho otorgado a los individuos bajo leyes y regulaciones como el GDPR. Esto significa que las empresas que almacenan los datos personales de un individuo deben ser capaces de eliminarlos a solicitud de este. Debido a que los datos pueden estar dispersos en varios sistemas, puede ser técnicamente complicado para estas empresas identificarlos y removerlos de todos los lugares. Incluso cuando se ejecute correctamente, existe el riesgo de que los datos eliminados puedan restaurarse a partir de copias de seguridad en el futuro, lo que podría crear riesgos legales y financieros.
Advertencia
MongoDB no garantiza que la solución y las técnicas descritas en este artículo cumplan con todos los requisitos regulatorios sobre el derecho de supresión. Su organización debe determinar las medidas adecuadas y suficientes para cumplir con requisitos regulatorios como el RGPD.
La aplicación de ejemplo de Destrucción de Criptomonedas muestra una forma de implementar el derecho de borrado. La aplicación de demostración es una aplicación web en Python (Flask) con una interfaz para añadir usuarios, iniciar sesión e introducir datos. También incluye una página de "Administración" para mostrar la funcionalidad de destrucción de criptomonedas.
Puede instalar y ejecutar la aplicación siguiendo las instrucciones en el Repositorio de GitHub.
¿Qué es el crypto-shredding?
El crypto-shredding, también llamado borrado criptográfico, es una técnica de destrucción de datos donde, en lugar de destruir los datos cifrados, se destruyen las claves de cifrado necesarias para descifrarlos. Esto vuelve los datos indescifrables.
Por ejemplo, imagina que estás almacenando datos para varios usuarios. Comienza por asignar a cada usuario su propia llave de cifrado de datos (DEK) única y la asigna a ese cliente.
En el diagrama, “Usuario A” y “Usuario B” tienen su propio DEK único en el almacén de claves. Cada clave se utiliza para cifrar o descifrar datos para su respectivo usuario:

Supongamos que desea eliminar todos los datos del Usuario B. Si elimina su DEK, ya no podrá descifrar sus datos. Todo el contenido del almacén de datos se convierte en texto cifrado indescifrable. Los datos del Usuario A no se ven afectados, ya que su DEK sigue existiendo:

¿Qué es CSFLE?
Con CSFLE, las aplicaciones pueden encriptar campos confidenciales en los documentos antes de transmitir los datos al servidor. Incluso cuando la base de datos está utilizando datos en la memoria, nunca están en texto plano. La base de datos almacena y transmite datos cifrados que sólo el cliente puede descifrar.
CSFLE utiliza cifrado de sobre, que es la práctica de cifrar datos de texto simple con una clave de datos, que a su vez está cifrada por una clave de sobre de nivel superior (también conocida como "clave maestra del cliente" o CMK).

Gestión de claves de encriptación
Por lo general, los CMK se gestionan mediante un Key Management Service (KMS). CSFLE soporta múltiples KMS, incluidos Amazon Web Services (AWS), Azure Key Vault, Google Cloud Platform (GCP) y almacenes de claves que soportan el estándar KMIP, como Hashicorp Keyvault. La aplicación de muestra utiliza Amazon Web Services como KMS.
Cifrado automático y explícito
CSFLE se puede utilizar en modo automático o explícito, o una combinación de ambos. La aplicación de ejemplo utiliza cifrado explícito.
Con el cifrado automático, se realizan operaciones cifradas de lectura y escritura basadas en un esquema de cifrado definido, por lo que no se necesita que el código de la aplicación especifique cómo cifrar o descifrar los campos.
Con el cifrado explícito, usa la librería de cifrado del driver de MongoDB para cifrar o descifrar manualmente campos en su aplicación.
Recorrido por la aplicación de muestra
La aplicación de ejemplo utiliza CSFLE con cifrado explícito y Amazon Web Services como KMS:

Agregar usuarios
La aplicación crea una instancia de ClientEncryption clase inicializando un objeto app.mongodb_encryption_client. Este cliente de cifrado se encarga de generar las DEK y luego cifrarlas mediante una CMK de AWS KMS.
Cuando un usuario se registra, la aplicación genera un DEK único para ellos usando el método create_data_key, y luego devuelve el data_key_id:
# flaskapp/db_queries.py def create_key(userId): data_key_id = \app.mongodb_encryption_client.create_data_key (kms_provider, master_key, key_alt_names=[userId]) return data_key_id
La aplicación utiliza este método al guardar la información del usuario:
# flaskapp/user.py def save(self): dek_id = db_queries.create_key(self.username) result = app.mongodb[db_name].user.insert_one( { "username": self.username, "password_hash": self.password_hash, "dek_id": dek_id, "createdAt": datetime.now(), } ) if result: self.id = result.inserted_id return True else: return False
Agregar y cifrar datos
Una vez registrado, un usuario puede iniciar sesión e introducir datos como pares clave-valor a través de un formulario de ingreso:

La base de datos almacena estos datos en una colección de MongoDB llamada "data", donde cada documento incluye el nombre de usuario y el par clave-valor:
{ "name": "shoe size", "value": "10", "username": "tom" }
La aplicación de ejemplo cifra los campos value y username, pero no el name. La aplicación cifra los campos con la DEK del usuario y un algoritmo de cifrado específico:
# flaskapp/db_queries.py # Fields to encrypt, and the algorithm to encrypt them with ENCRYPTED_FIELDS = { # Deterministic encryption for username, because we need to search on it "username": Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, # Random encryption for value, as we don't need to search on it "value": Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random, }
La función insert_data toma un documento no cifrado y recorre los ENCRYPTED_FIELDS para cifrarlos:
# flaskapp/db_queries.py def insert_data(document): document["username"] = current_user.username # Loop over the field names (and associated algorithm) we want to encrypt for field, algo in ENCRYPTED_FIELDS.items(): # if the field exists in the document, encrypt it if document.get(field): document[field] = encrypt_field(document[field], algo) # Insert document (now with encrypted fields) to the data collection app.data_collection.insert_one(document)
Si el campo especificado existe en el documento, la función llama a encrypt_field para cifrarlo utilizando el algoritmo especificado:
# flaskapp/db_queries.py # Encrypt a single field with the given algorithm def encrypt_field(field, algorithm): try: field = app.mongodb_encryption_client.encrypt( field, algorithm, key_alt_name=current_user.username, ) return field except pymongo.errors.EncryptionError as ex: # Catch this error in case the DEK doesn't exist. Log a warning and # re-raise the exception if "not all keys requested were satisfied" in ex._message: app.logger.warn( f"Encryption failed: could not find data encryption key for user: {current_user.username}" ) raise ex
Después de agregar datos, puedes visualizarlos en la aplicación web:

Borrado de una llave de cifrado
Ahora veamos qué sucede al eliminar la DEK. La aplicación de ejemplo lo hace desde una página de administración, que debería estar restringida solo a quienes tengan autorización para administrar claves:

La opción "Borrar llave de cifrado de datos" remueve la DEK, pero deja los datos cifrados del usuario en su lugar. Después de eso, la aplicación no podrá descifrar los datos. Intentar recuperar los datos del usuario conectado da error:

Nota
Después de borrar el DEK, la aplicación aún podría ser capaz de desencriptar y mostrar datos hasta que su caché caduque, hasta 60 segundos después.
Pero, ¿qué es lo que realmente queda en la base de datos? Puedes revisar la información volviendo a la página de administración y haciendo clic en Fetch data for all usersEsta vista no genera una excepción si la aplicación no puede descifrar los datos. En cambio, muestra exactamente lo que está almacenado en la base de datos.
Aunque no hayas borrado los datos del usuario, como la llave de cifrado de datos ya no existe, la aplicación solo puede mostrar el texto cifrado de los campos "username" y "value".

Aquí está el código utilizado para obtener estos datos. Utiliza una lógica similar al método encrypt mostrado anteriormente. La aplicación ejecuta una operación find sin ningún filtro para recuperar todos los datos, luego recorre el diccionario ENCRYPTED_FIELDS para descifrar campos:
# flaskapp/db_queries.py def fetch_all_data_unencrypted(decrypt=False): results = list(app.data_collection.find()) if decrypt: for field in ENCRYPTED_FIELDS.keys(): for result in results: if result.get(field): result[field], result["encryption_succeeded"] = decrypt_field(result[field]) return results
Se llama a la función decrypt_field para cada campo que se va a descifrar, pero en este caso la aplicación detecta el error si no puede descifrarlo correctamente debido a una DEK faltante:
# flaskapp/db_queries.py # Try to decrypt a field, returning a tuple of (value, status). This will be either (decrypted_value, True), or (raw_cipher_text, False) if we couldn't decrypt def decrypt_field(field): try: # We don't need to pass the DEK or algorithm to decrypt a field field = app.mongodb_encryption_client.decrypt(field) return field, True # Catch this error in case the DEK doesn't exist. except pymongo.errors.EncryptionError as ex: if "not all keys requested were satisfied" in ex._message: app.logger.warn( "Decryption failed: could not find data encryption key to decrypt the record." ) # If we can't decrypt due to missing DEK, return the "raw" value. return field, False raise ex
También puede usar el shell de mongosh para verificar directamente en la base de datos y comprobar que no hay nada legible:

En este punto, los datos cifrados del usuario aún están presentes. Alguien podría acceder a ellos restaurando su clave de cifrado, por ejemplo, desde una copia de seguridad de la base de datos.
Para evitarlo, la aplicación de muestra utiliza dos clústeres de bases de datos separados: uno para almacenar datos y otro para almacenar DEKs (el "bóveda de claves"). Utilizar clústeres separados desacopla la restauración de copias de seguridad para los datos de la aplicación y la bóveda de claves. Restaurar el clúster de datos desde una copia de seguridad no restablece ninguna DEK que haya sido eliminada del clúster del almacén de claves.
Conclusión
El cifrado a nivel de campo del lado del cliente simplifica el olvido de ciertos datos. Al eliminar las claves de datos, se pueden olvidar eficazmente los datos existentes en diferentes bases de datos, colecciones, copias de seguridad y registros.
En una aplicación de producción, también puedes borrar los datos cifrados en sí mismos, además de remover la clave de cifrado. Este enfoque de "defensa en profundidad" ayuda a garantizar que los datos estén realmente eliminados. Implementar el borrado criptográfico además de la eliminación de datos minimiza el impacto si una operación de eliminación falla, o no incluye datos que deberían haberse eliminado.