Diferentes formas de anonimizar dados (e hash não é uma delas)
Anonimizar dados é essencial para proteger a privacidade, mas será que você está fazendo isso da forma correta? Muita gente acredita que gerar um simples hash, como transformar o nome rafael
em 9135d8523ad3da99d8a4eb83afac13d1
, já resolve o problema, mas ele não acaba aí.
Neste artigo eu vou te mostrar por que um hash sozinho não é suficiente para anonimizar dados, e quais cuidados você deve ter quando estiver trabalhando com a anonimização. É o tipo de conhecimento que só de entender a base, você já irá se diferenciar de muita gente, mesmo que o assunto seja muito mais profundo.
Gerar um hash torna o dado anônimo?
Essa foi a pergunta que o Edward Felten respondeu em 2012, no blog do FTC, quando estava no cargo de Chief Technologist.
Um hash é uma função matemática: você dá a ele um valor de entrada e a função emite um valor de saída; e a mesma entrada sempre produz a mesma saída. O que torna um hash especial é que ele é tão imprevisível quanto uma função matemática pode ser — ele é projetado para que não haja rima ou razão para seu comportamento, exceto pela regra de que a mesma entrada sempre produz a mesma saída.
Como exemplo, vamos considerar "anonimizar" um SSN (algo como nosso CPF, porém secreto) utilizando o SHA-1. Essa função retornará uma string similar à b0254c86634ff9d0800561732049ce09a2d003e1
. Um SSN é composto por 9 números, então é bem diferente do resultado do SHA-1.
Apesar disso, é bem fácil descobrir qual é o SSN criptografado com uma função como o SHA-1. O analista simplesmente adivinha o SSN por força bruta: ele enumera todos os possíveis SSNs e faz o hash de cada um. Depois, pode comparar a string acima com a tabela de SSNs que ele gerou.
Nos comentários, o Edward Felten dá como alternativa usar um "salt longo e secreto" para o hash, e isso é abordado nos outros artigos que mencionarei.
Como anonimizar dados corretamente, se o hash não é o suficiente?
O texto anterior possivelmente te deixou com esta dúvida, e coincidentemente é exatamente uma pergunta feita no Security Stack Exchange. A resposta mais votada nos dá duas alternativas para a anonimização:
- Usar tokenização. Isso significa que você cria um banco de dados separado com IDs gerados aleatoriamente mapeando para o valor desejado. Você então insere o token em vez da identidade real.
- Se você não precisa mapear os dados de volta, pode usar, por exemplo, um HMAC com um segredo longo gerado aleatoriamente. Sem o segredo, você não pode utilizar força bruta para adivinhar os IDs originais, mesmo quando eles consistam em apenas 1 único caractere.
Usar um HMAC é, na verdade, a maneira correta de usar um "salt secreto" (um salt nunca é considerado secreto na criptografia). Ou seja, é o que Edward Felten mencionou no blog do FTC.
Essas são as respostas curtas, mas ainda assim, anonimizar dados não é algo tão simples, e mesmo seguindo essas recomendações, você pode não estar fazendo o suficiente. O próximo link é um mergulho profundo no assunto.
O falso fascínio do hash para anonimização
Este é o título do artigo publicado no blog da Teleport (uma empresa que não conheço, mas o artigo é bom).
Ao longo do artigo, vamos usar a seguinte tabela como "base de dados". Considere que são registros de login.
Timestamp | IP | Usuário |
---|---|---|
2018-04-15 13:01 | 1.2.3.4 | 45d9908cf9f290f7097bf8152c288055275ebe93f2dc3781c8a1c60a43cd6ae5 |
2018-04-05 08:05 | 5.6.7.8 | e9e326d5f3b4741fe5967b5f9f3997e6275331ba18567ef9ef9e0e3a00e78371 |
2018-04-16 12:27 | 9.1.2.3 | 4135aa9dc1b842a653dea846903ddb95bfb8c5a10c504a7fa16e10bc31d1fdf0 |
A tabela acima utiliza o SHA256 para criptografar o nome do usuário. Apesar de parecer anônimo e difícil de adivinhar na força bruta, caso você esteja procurando por um usuário específico, como knisbet
, fica fácil descobrir se ele está na base de dados ou não.
É um caso parecido com o SSN mencionado no blog do FTC, mas aqui já sabemos de antemão o que estamos procurando (informações sobre um usuário específico), precisando apenas gerar o hash para o nome de usuário desejado e verificar se ele está na base de dados.
Tornar o hash mais lento, ao usar bcrypt, por exemplo, também não resolve esse problema, porque o dado que queremos descobrir é uma string pública e fácil de adivinhar, como o nome de usuário ou um endereço de e-mail. Para senhas, isso serve porque é uma string difícil de adivinhar.
Mas já sabemos resolver o problema do hash, certo?
Suponha que o problema do hash tenha sido resolvido e estamos usando id
s aleatórios, como a resposta do Security Stack Exchange mencionou, ou HMACs. Ainda assim, temos outros problemas.
Imagine que um usuário declarou em alguma rede social, como o X, ou num site de status, que ocorreu um problema no sistema e ele precisou acessar no dia 15/04/2018, por volta das 13hrs, para resolver o problema. Se não houver muitos outros registros nesse momento, é fácil ver que é o primeiro usuário neste banco de dados.
E se você estava conversando com outra pessoa, que entrou de férias no dia 5 de abril, também consegue identificá-la, porque o último acesso foi no dia 5, e você só precisa identificar algum registro que atenda este requisito.
Caso outro conjunto de dados tenha sido comprometido, e nele é possível ver que o usuário alex
utilizou o IP 9.1.2.3 no dia 12 de abril, também será possível identificá-lo na tabela acima.
Combinar dados anonimizados que podem ser correlacionados a outras partes dos seus dados que não são anonimizadas, em muitos casos torna trivial desmascarar usuários em conjuntos de dados anonimizados. Normalmente, você só precisa de alguns pontos de dados com precisão relativamente baixa para desmascarar um grande conjunto de dados.
Então, como anonimizar os dados?
No artigo, o autor diz que a forma de anonimizar depende inteiramente do conjunto de dados e de como ele deve ser usado.
Na Teleport, a maneira que escolheram anonimizar os dados é gerando HMACs com um segredo que é relevante apenas para o cluster Teleport. Isso significa que o algoritmo usado para calcular knisbet
-> 45d99...
depende de uma chave secreta e imprevisível que vive na rede dos clientes, e que a empresa não tem acesso à essa chave. Cada cluster também usa sua própria chave, então se houver um vazamento nos segredos, isso limita o potencial desmascaramento a apenas um único cliente.
E o mais importante, a empresa coleta apenas dados suficientes para cumprir o propósito declarado. Quanto menos pontos de dados são coletados, menor a oportunidade de alguém correlacionar os dados.
Há várias maneiras de melhorar isso, sendo algumas:
- Fazer com que os clusters rotacionem seus segredos todo mês, para que os dados coletados não possam ser correlacionados mês a mês.
- Armazenar apenas hashes parciais, o que tornaria um ataque de força bruta mais difícil.
Uma outra alternativa
Como mencionado na resposta do Security Stack Exchange, uma alternativa é, em vez de anonimizar os dados que você deseja proteger por meio de um algoritmo, gerar uma tabela de consulta de números de ID ou UUIDs para substituir o texto. Então knisbet
= 1
, alex
= 2
, etc. e armazenar isso em um banco de dados em um domínio de segurança separado com controles de acesso separados.
Dessa forma, você sempre tem que consultar a tabela de referência e fazer uma troca de dados reais por dados anonimizados. Isso tem a vantagem de não poder ser quebrado pelo próprio algoritmo, mas ainda tem a fraqueza de que se essa tabela for comprometida ou incluir informações que podem ser correlacionadas, o conjunto de dados pode ser trivialmente desmascarado.
Não é tão simples, mas melhorar não é tão complicado
Como vimos, usar um hash não é suficiente. Esse seria apenas o “primeiro passo”. Um HMAC já é algo melhor, mas a verdadeira proteção de dados exige uma abordagem mais completa, que leva em consideração as relações entre os dados e a possibilidade de outros vazamentos dentro do sistema. A chave aqui é entender que anonimizar dados não se trata apenas de aplicar uma função matemática, mas sim de garantir que as informações que você está protegendo não possam ser facilmente correlacionadas e desmascaradas.
Um dos grandes insights que eu tive lendo os artigos foi sobre o uso de HMAC com uma chave secreta exclusiva para cada cliente, permitindo que o processo de anonimização ocorra sem que seu sistema precise conhecer a chave, além da sugestão de rotacionar o segredo, minimizando os danos em caso de vazamentos. A análise de correlação entre os dados também foi um ponto bem relevante.
Anonimizar dados corretamente não é simples, mas sair do zero é fácil. Pense de forma estratégica sobre como proteger as informações sensíveis, antecipando possíveis pontos de falha. Esse conhecimento é um diferencial que pode não só melhorar a segurança dos seus dados, mas também destacar você como profissional. Não é comum encontrar profissionais com essa preocupação por aí, ainda mais num momento onde tantos desenvolvedores “são formados em seis meses”.
Recentemente eu estava pensando exatamente nessa questão. Não sabia dos nomes exatos de alguns termos que você usou, mas tenho alguma noção dos conceitos principais. Estava pensando em fazer um banco de dados pra lidar somente com dados sensíveis. Ele usaria um esquema de rotação de chaves derivadas de uma chave mestre que fica em armazenada em um lugar sem conexão com a internet. Essas chaves são rotacionadas semanalmente (elas são geradas previamente por um algoritmo). Dai pra armazenar essas chaves seria usado uma blockchain que guarda partes dessas chaves de em blocos não ligados de forma consecutiva (a ideia seria fazer um tipo de randomização aqui). (Nessa parte eu também pensei em guardar os dados em si dessa forma, quebrando eles em blocos de binários e randomizando na blockchain, mas acho que algo assim, apesar de poder funcionar, gera tradeoffs colaterais, que dificultam o gerenciamento dos dados - mas que também é possível resolver). Enfim, viajei bastante nisso, dai vi que tem algumas soluções que fazem mais ou menos isso:
Seria um projeto interessante, e talvez fosse bem útil pra outras pessoas e empresas. Cheguei a pensar nisso porque estou querendo resolver outro problema, dai queria ter um banco de dados bem seguro e vi que as soluções que tem hoje não fazem troca de chaves de criptografia (recriptografar os dados) de forma automatizada. Seria interessante. Claro que um sistema como esse exigiria um alto grau de computação por ter recriptografia sendo feita, mas acho que o esquema de blockchain e distribuição de trabalho poderia ser usado também aqui nesse caso pra conseguir fazer isso de forma rápida (paralelismo e assincronismo). Enfim, uma ideia bacana, mas ainda precisaria ser analisados vários pontos.
Clique aqui para ver o que o hash representa.
Conforme o próprio artigo: > [In case you’re wondering, the b02 value is not really the hash of my SSN. It is the hash of the text string “my SSN”. There is no way I would publish the hash of my actual SSN.]Um texto de chamada
Um texto. > Uma citação _ipsis litteris_, por exemplo.Um texto de chamada
Um texto. > Uma citação _ipsis litteris_, por exemplo.rafael, sei que a ideia não faz mais sentido devido aos diversos vazamentos de dados que ocorreram recentemente, enriquecendo bancos de dados clandestinos por aí. Pensando numa maneira de dificultar, imaginei o seguinte conjunto de dados pessoais de um cliente (fictício) de uma empresa (fictícia).
NOME COMPLETO : JOAO DA SILVA SÓ
DATA DE NASCIMENTO: 29/02/2000
CPF : 987.654.321-00
RG : 12.234.567-X SSP/RR
ENDEREÇO : AVENIDA ESPERANÇA SEM FIM, 789, BAIRRO LOGO ALI
CEP : 97531-024 - 5105507 - VILA BELA DA SANTÍSSIMA TRINDADE - MT
CELULAR : +5565987654321
EMAIL : JOAODASILVASOH@GMAIL.COM
PASSPHRASE CLIENTE: QUALQUER COISA VALE DESDE QUE SO O CLIENTE SE LEMBRE
SALT : 5d60adc890a3dc0bd7b9b621edac9272
ÚLTIMA ATUALIZAÇÃO: 01/02/2024 14:15:16
Hoje, corre o risco de cadastros assim estarem sendo subidos para sistemas na nuvem. Porém, em vez subir esses ~600 bytes, poderiam ser apenas 32 bytes gerados pelo SHA256: be6034da95b490d59eb881c06b18e2092913985155bfb56d3c1e0b06eab99b2b
As colisões de hash são evitadas devido a existência da passphrase e do salt mesmo que o cliente forneça poucos dados pessoais. A desanonimização, quando necessária, ocorre em sistema offline fora das vistas de qualquer ataque online. Se ocorrer a atualização dos dados, um novo hash é gerado. E ainda, se esses hashes fizerem parte de uma blockchain, o campo ÚLTIMA ATUALIZAÇÃO torna-se redundante.
De uma maneira geral, os únicos campos que realmente são livres para alteração a qualquer tempo e quantas vezes precisar são PASSPHRASE CLIENTE
, SALT
e, consequentemente, o campo ÚLTIMA ATUALIZAÇÃO
. Destes, o primeiro é guardado com o cliente, os demais com a empresa junto com o hash. Perdendo-se a passphrase, um novo cadastro pode ser gerado. Conforme prevê a LGPD em seu artigo 18, "o titular poderá a qualquer momento e mediante requisição, a eliminação dos dados pessoais tratados com o consentimento do titular, exceto nas hipóteses previstas no art. 16 desta lei". Com tal método, a simples omissão ou perda da passphrase dá ao titular dos dados o poder de praticamente anonimizá-los para sempre.
Talvez tenha ficado a dúvida, como o cliente ficará com esse cadastro? Assinando digitalmente o hash.
Estou em um projeto no trabalho e minha maior preocupação tem sido justamente a anonimização dos dados. Só de ler o seu post já foi o suficiente para abrir mais a minha mente ^-^
Eu já tinha pensado sobre o segredo do hash ficar apenas sobre o domínio do cliente, mas caso talvez por leiguismo: 1 - Me pareceu que o cliente não poderia se responsabilizar por uma informação tão importante. 2 - Como criar uma aplicação onde a informação está com o cliente, e se ele trocar de dispositivo como faria para recuperar os dados.
Não sou da área de segurança então talvez sejam perguntas bobas, mas foram as duas que eu mais fiquei assim pensando.