O aplicativo de amostra Crypto Sredding demonstra como você pode usar a criptografia no nível do campo do lado do cliente do MongoDB (CSFLE) para fortalecer os procedimentos de remoção de dados confidenciais.
Sobre o aplicativo de amostra
O direito ao apagamento, também conhecido como direito a ser Esquecido, é um direito concedido a individuais por meio de Leis e regulamentos como o GDPR. Isso significa que as empresas que armazenam os dados pessoais de um indivíduo devem poder excluí-los quando solicitado. Como os dados podem estar espalhados por vários sistemas, pode ser técnico um desafio para essas empresas identificá-los e removê-los de todos os lugares. Mesmo quando executados corretamente, existe o risco de que os dados excluídos possam ser restaurados a partir de backups no futuro, potencialmente criando riscos legais e financeiros.
Aviso
O MongoDB não garante que a solução e as técnicas descritas neste artigo atendam a todos os requisitos regulatórios em torno do direito ao apagamento. Sua organização deve determinar medidas apropriadas e suficientes para cumprir os requisitos regulatórios, como o GDPR.
O aplicação de amostra Crypto Sredding demonstra uma maneira de implementar um direito ao apagamento. O aplicação de demonstração é um aplicação web Python (Flask) com um frontend para adicionar usuários, fazer login e inserir dados. Ele também inclui uma página de "Administrador" para mostrar a funcionalidade de fragmentação de criptografia.
Você pode instalar e executar o aplicação seguindo as instruções no repositório do Github.
O que é o Crypto-Shredding?
A criptografia, também chamada de apagamento criptográfico, é uma técnica de destruição de dados em que, em vez de destruir dados criptografados, você destrói as chaves de criptografia necessárias para descriptografá-los. Isso torna os dados indecifráveis.
Por exemplo, suponha que você esteja armazenando dados para vários usuários. Você começa dando a cada usuário sua própria chave de criptografia de dados (DEK) exclusiva e mapeando-a para esse cliente.
No diagrama, "Usuário A" e "Usuário B" têm sua própria DEK exclusiva no armazenamento de chaves. Cada chave é usada para criptografar ou descriptografar dados para seu respectivo usuário:

Suponhamos que você queira remover todos os dados do usuário B. Se você remover a DEK do usuário B, não poderá mais descriptografar seus dados. Tudo no armazenamento de dados se torna texto cifrado indecifrável. Os dados do Usuário A não são afetados, pois sua DEK ainda existe:

O que é o CSFLE?
Com o CSFLE, os aplicativos podem criptografar campos confidenciais em documentos antes de transmitir dados para o servidor. Mesmo quando os dados estão sendo usados pelo banco de dados na memória, eles nunca estão em texto sem formatação. O banco de dados armazena e transmite dados criptografados que são apenas decifrados pelo cliente.
O CSFLE usa criptografia de envelope, que é a prática de criptografar dados de texto simples com uma chave de dados, que é criptografada por uma chave de envelope de nível superior (também conhecida como "chave mestra do cliente" ou CMK).

Gerenciamento das chaves de criptografia
CMKs geralmente são gerenciadas por um KMS (KMS). CSFLE é compatível com vários KMSs, incluindo Amazon Web Services (Amazon Web Services), Azure Key Vault, Google Cloud Platform (GCP) e armazenamentos de chaves compatíveis com o padrão KMIP, como o Hashicorpo Keyvault. O aplicativo de amostra usa Amazon Web Services como KMS.
Criptografia automática e explícita
O CSFLE pode ser usado no modo automático ou explícito, ou em uma combinação de ambos. O aplicativo de amostra usa criptografia explícita.
Com a criptografia automática, você executa operações de leitura e gravação criptografadas com base em um esquema de criptografia definido, portanto, não precisa do código do aplicação para especificar como criptografar ou descriptografar campos.
Com a criptografia explícita, você usa a biblioteca de criptografia do driver MongoDB para criptografar ou descriptografar manualmente campos em seu aplicação.
Amostra de passo a passo do aplicativo
O aplicativo de amostra usa CSFLE com criptografia explícita e Amazon Web Services como KMS:

Adicionando usuários
O aplicativo instancia a classe ClientEncryption
inicializando um objeto app.mongodb_encryption_client
. Esse cliente de criptografia é responsável por gerar DEKs e, em seguida, criptografá-los usando um CMK do Amazon Web Services KMS.
Quando um usuário se inscreve, o aplicação gera uma DEK exclusiva para ele usando o método create_data_key
e, em seguida, retorna o 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
O aplicativo usa este método ao salvar as informações do usuário:
# 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
Adicionar e criptografar dados
Depois de registrado, o usuário pode fazer login e inserir dados como pares de valores-chave por meio de um formulário de entrada:

O banco de dados armazena esses dados em uma coleção MongoDB chamada "dados", onde cada documento inclui o nome de usuário e o par chave-valor:
{ "name": "shoe size", "value": "10", "username": "tom" }
O aplicativo de amostra criptografa os campos value
e username
, mas não o name
. O aplicativo criptografa campos com o DEK do usuário e um algoritmo de criptografia especificado:
# 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, }
A função insert_data
pega um documento não criptografado e faz um loop sobre ENCRYPTED_FIELDS
para criptografá-lo:
# 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)
Se o campo especificado existir no documento, a função chamará encrypt_field
para criptografá-lo usando o 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
Depois de adicionar os dados, você pode visualizá-los no aplicativo da web:

Excluindo uma chave de criptografia
Agora vejamos o que acontece quando você exclui a DEK. O aplicativo de exemplo faz isso a partir de uma página de administração, que deve ser restrita apenas às pessoas com autorização para gerenciar chaves:

A opção "Excluir chave de criptografia de dados" remove a DEK, mas deixa os dados criptografados do usuário no lugar. Depois disso, o aplicação não pode mais descriptografar os dados. Tentando recuperar os dados do usuário conectado gera um erro:

Observação
Depois de excluir a DEK, o aplicação ainda pode descriptografar e mostrar dados até que o cache expire, até 60 segundos depois.
Mas o que é realmente deixado no banco de dados? Você pode revisar as informações retornando à página do administrador e clicando em Fetch data for all users. Esta visualização não lança uma exceção se o aplicação não puder descriptografar os dados. Em vez disso, mostra exatamente o que está armazenado no banco de dados.
Mesmo que você não tenha realmente excluído os dados do usuário, como a chave de criptografia de dados não existe mais, o aplicação só pode mostrar o texto cifrado para os campos criptografados "nome de usuário" e "valor".

Aqui está o código usado para buscar esses dados. Ele usa lógica semelhante ao método encrypt
mostrado anteriormente. O aplicação executa uma operação find
sem nenhum filtro para recuperar todos os dados e, em seguida, faz um loop no dicionário ENCRYPTED_FIELDS
para descriptografar 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
A função decrypt_field
é chamada para cada campo a ser descriptografado, mas, nesse caso, o aplicação detecta o erro se não conseguir descriptografá-lo com êxito devido a uma DEK ausente:
# 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
Você também pode usar o shell mongosh para verificar diretamente no banco de dados, para provar que não há nada legível:

Neste ponto, os dados criptografados do usuário ainda estão presentes. alguém poderia obter acesso a ele restaurando sua chave de criptografia, como a partir de um backup de banco de dados .
Para evitar isso, o aplicação de amostra usa dois clusters de banco de dados separados: um para armazenar dados e outro para armazenar DEKs (o "cofre de chaves"). O uso de clusters separados dissocia a restauração dos backups de dados de aplicação e do cofre de chaves. Restaurar o cluster de dados a partir de um backup não restaura nenhum DEKs que foi excluído do cluster de cofre de chaves.
Conclusão
A criptografia no nível do campo do lado do cliente pode simplificar a tarefa de "esquecer" determinados dados. Ao excluir chaves de dados, você pode esquecer efetivamente os dados existentes em diferentes bancos de dados, collections, backups e logs.
Em um aplicação de produção , você também pode excluir os próprios dados criptografados , além de remover a chave de criptografia. Essa abordagem de "defesa em profundidade" ajuda a garantir que os dados realmente desapareçam. A implementação de fragmentação criptográfica além da exclusão de dados minimiza o impacto se uma operação de exclusão falhar ou não incluir dados que deveriam ter sido apagados.