Menu Docs
Página inicial do Docs
/
Manual do banco de dados
/ / / / /

Implementando o direito ao apagamento com o CSFLE

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.

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.

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:

Um armazenamento de chave de criptografia de dados com dois usuários

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:

Excluindo a chave de criptografia de dados do Usuário B

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).

Diagrama de criptografia de envelope

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.

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.

O aplicativo de amostra usa CSFLE com criptografia explícita e Amazon Web Services como KMS:

Um exemplo da UI de fragmentação de criptomoedas

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
@aws_credential_handler
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

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:

Uma interface de usuário de exemplo para adicionar dados

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
@aws_credential_handler
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:

Dados de amostra na UI

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 página de administração do aplicativo de exemplo

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:

Uma mensagem de erro ao tentar recuperar dados criptografados sem uma chave

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".

Texto cifrado bruto do banco de dados do aplicativo de demonstração

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:

saída de shell mongosh ao consultar o banco de dados

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.

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.

Voltar

Usar criptografia no nível do campo automática no lado do cliente com KMIP

Nesta página