Suponha que eu precise criptografar certos campos de tabela de um banco de dados MySQL . Além disso, preciso pesquisar alguns desses campos que criptografei.
Como alguém iria pesquisar esses campos de qualquer maneira?
Descriptografar cada registro passo a passo não é uma opção: suponha que eu tenha vários milhares de registros. Levaria muito tempo e espaço para descriptografar cada registro e verificar se cada registro corresponde à pesquisa.
ATUALIZAÇÃO 2012-09-07
Adicionar mais detalhes ao esquema do banco de dados seria OK , já que estou prestes a implementar um novo aplicativo. Além disso, preciso estender os aplicativos atualmente em execução na produção. Mas mesmo para esses aplicativos, adicionar mais detalhes seria bom.
ATUALIZAÇÃO 2012-09-08
A criptografia é o núcleo desta questão.
As restrições de acesso, conforme proposto por algumas respostas, já se aplicam - mas não se enquadram no requisito formal de criptografar dados.
Este requisito formal não é o Padrão de Segurança de Dados da Indústria de Cartões de Pagamento [PCI].
Obviamente, eles não devem ser vistos, portanto, pesquisá-los seria problemático.
Um truque que usei no passado é fazer o hash dos dados criptografados antes de criptografá-los e armazenar o hash em uma coluna indexada. Claro, isso só funciona se você estiver pesquisando o valor total; valores parciais não terão o mesmo hash.
Você provavelmente poderia estender isso fazendo um índice de "texto completo" de hashes, se necessário, mas pode ficar complicado muito rápido.
TERMO ADITIVO
Foi sugerido que eu adicione uma nota de rodapé à minha resposta por um debate bastante longo no bate-papo sobre vulnerabilidade a ataques de dicionário, então discutirei esse possível risco de segurança para a abordagem acima.
Ataque de dicionário: um ataque de dicionário é quando alguém pré-hash uma lista de valores conhecidos e compara os hashes com sua coluna com hash no banco de dados. Se eles puderem encontrar uma correspondência, é provável que o valor conhecido seja realmente o que está sendo hash (não é definitivo, porque os hashes não são garantidos como exclusivos). Isso geralmente é mitigado pelo hash do valor com um "sal" aleatório acrescentado ou prefixado para que o hash não corresponda ao dicionário, mas a resposta acima não pode usar um sal porque você perde a capacidade de pesquisa.
Esse ataque é perigoso ao lidar com coisas como senhas: se você criar um dicionário de hashes de senhas populares, poderá pesquisar rapidamente na tabela esse valor de hash e identificar um usuário que tenha essa senha e extrair credenciais para roubar a identidade desse usuário .
É menos perigoso para itens com alto grau de cardinalidade, como SSNs, números de cartão de crédito, GUIDs, etc. ).
A razão para isso é que para que um ataque de dicionário funcione, você precisa ter um dicionário pré-construído de valores possíveis e seus hashes. Você poderia, em teoria, construir um dicionário de todos os SSNs possíveis (um bilhão de linhas, supondo que todas as permutações de formatação sejam removidas; várias dezenas de trilhões de entradas para cartões de crédito)... basicamente se torna comparável a um ataque de força bruta em que você está investigando sistematicamente todos os valores.
Você também pode procurar um SSN específico ou número de cartão de crédito, se estiver tentando corresponder um SSN a uma pessoa. Novamente, geralmente não é o ponto de um ataque de dicionário, mas é possível fazer isso, portanto, se esse é um risco que você precisa evitar, minha resposta não é uma boa solução para você.
Então você tem isso. Como acontece com todos os dados criptografados, eles geralmente são criptografados por um motivo, portanto, esteja ciente de seus dados e do que você está tentando protegê-los.
Você pode querer dar uma olhada no CryptDB . É um front-end para MySQL e PostgreSQL que permite armazenamento e consulta transparente de dados criptografados. Ele funciona criptografando e descriptografando dados à medida que passam entre o aplicativo e o banco de dados, reescrevendo consultas para operar nos dados criptografados. e ajustando dinamicamente o modo de criptografia de cada coluna para expor apenas as informações necessárias para as consultas que o aplicativo usa.
Os vários métodos de criptografia usados pelo CryptDB incluem:
RND , um esquema de criptografia totalmente seguro IND-CPA que não vaza informações sobre os dados (exceto sua presença e, para tipos de comprimento variável, comprimento), mas permite apenas armazenamento e recuperação, sem consultas.
DET , uma variante de RND que é determinística, de modo que dois valores idênticos (na mesma coluna) criptografam para o mesmo texto cifrado. Suporta consultas de igualdade do formulário
WHERE column = 'constant'
.OPE , um esquema de criptografia de preservação de ordem que oferece suporte a consultas de desigualdade, como
WHERE column > 'constant'
.HOM , um esquema de criptografia parcialmente homomórfico (Paillier) que permite adicionar valores criptografados multiplicando os textos cifrados. Suporta
SUM()
consultas, adição e incremento.SEARCH , um esquema que suporta pesquisas de palavras-chave do formulário
WHERE column LIKE '% word %'
.JOIN e OPE-JOIN , variantes de DET e OPE que permitem que valores em colunas diferentes sejam comparados entre si. Suporta junções de igualdade e intervalo, respectivamente.
O verdadeiro poder do CryptDB é que ele adapta o método de criptografia de cada coluna dinamicamente às consultas que vê, de modo que os esquemas mais lentos e/ou menos seguros sejam usados apenas para colunas que os exigem. Há também vários outros recursos úteis, como encadear chaves de criptografia a senhas de usuário.
Se você estiver interessado, é aconselhável dar uma olhada nos documentos vinculados no site do CryptDB, particularmente "CryptDB: Protegendo a confidencialidade com o processamento de consultas criptografadas" de Popa, Redfield, Zeldovich e Balakrishnan ( SOSP 2011 ). Esses documentos também descrevem as várias compensações de segurança e desempenho envolvidas no suporte a diferentes tipos de consulta com mais detalhes.
Não entendo por que as respostas atuais não questionaram totalmente os requisitos, então vou perguntar e deixar como resposta.
Quais são as razões comerciais? Quais dados você precisa criptografar e por quê? Se você está procurando conformidade com o PCI, eu poderia escrever um ensaio.
Perguntas sobre sua exigência:
A segurança do RDBMS normalmente é feita com base em permissões que são impostas pelo usuário/função. Os dados normalmente são criptografados pelo RDBMS no disco, mas não nos dados colunares em si, pois isso não faz sentido para um aplicativo projetado para armazenar e recuperar dados com eficiência.
Restringir por usuário/função/api. Criptografar em disco. Se você estiver armazenando dados mais importantes, adoraria saber por que você está usando o MySQL.
Estou pesquisando sobre isso e me deparei com sua pergunta. Estou me inclinando para a abordagem descrita na seção 5.4 do artigo "Técnicas práticas para pesquisas em dados criptografados" http://www.cs.berkeley.edu/~dawnsong/papers/se.pdf
A essência básica é criar um índice que contenha palavras-chave criptografadas presentes no documento de pesquisa criptografado. O truque é também criptografar os locais no documento (ou banco de dados) onde essas palavras-chave estão presentes.
Programaticamente, uma solução eficiente é
O ponto é que 1 e 4 são conjuntos de dados significativamente menores do que recuperar e descriptografar todos os campos de todos os registros no início.
Espero que ajude.
Isso é possível com a funcionalidade de pesquisa completa usando as funções de criptografia interna do MYSQL.
Aqui está um exemplo:
!!! ESTOU USANDO MYSQL ENCODE() AQUI PARA SIMPLICIDADE, MYSQL_ENCODE AGORA É CONSIDERADO INSEGURO, USE UMA DAS OUTRAS FUNÇÕES INTERNAS DO MYSQL EM VEZ!!!
Como o comentário acima sugere, NÃO use ENCODE(), use uma das outras funções de criptografia Estou usando apenas ENCODE neste exemplo devido à sua simplicidade
Se você estiver fazendo isso em um aplicativo como php, você pode fazer isso em seu db gateway ou classes de repositório armazenando uma lista/matriz de colunas criptografadas de cada tabela dentro de sua respectiva classe de gateway.
Claro que este é um código muito grosseiro e inseguro que não deve ser usado em produção sem melhorias significativas. Mas deve servir ao seu propósito ao dar a ideia geral.
Então eu tive uma ideia que poderia fazer isso, mas é tudo conceitual.
Suponha que você tenha o valor "Lorem ipsum dolor sit amet" e queira fazer uma busca por "lorem". Uma maneira é que você pode pegar o original e dividi-lo em pedaços (em letras minúsculas) e colocá-los em uma segunda tabela. O valor inteiro (original) está na coluna da tabela original com row_id 123, mas uma nova tabela chamada "chunks" pode ter:
Pense nisso como um índice de substring, onde cada substring tem 2 caracteres.
Agora, quando um usuário deseja realizar uma pesquisa, você também divide isso e, em seguida, faz uma pesquisa. Se eles digitarem "
lo
", você verá quais IDs de linhas estrangeiras corresponderam. Mas se eles inserirem "lore
", você fará uma pesquisa por todos os IDs de linha estrangeiros que tenham um pedaço correspondente para "lo
", "or
", AND "re
".Até agora, não muito prático. No entanto, se o valor original "Lorem ipsum dolor sit amet" estiver criptografado ou com hash, você TAMBÉM poderá fragmentar as substrings de 2 caracteres, criptografá-las / hash e fazer uma pesquisa nos pedaços ou na string completa. Nenhuma descriptografia ou hashing é necessária.
A lógica seria:
Qualquer correspondência pode ser buscada na tabela original. Isso protegeria os dados em repouso, porque se a tabela de fragmentos estiver comprometida, eles não poderão fazer nada com um monte de valores criptografados/com hash de 2 caracteres. Você não pode pegar 2 substrings criptografadas/com hash e recombiná-las ou obter algo significativo delas.
Se eu sou o inventor e tenho que nomear isso, já que é semelhante, mas não exatamente o mesmo que fazer uma mesa de arco-íris, eu chamaria isso de "Fruity Pebbles Tables". Por causa dos pedaços.
Supondo que você esteja pesquisando em SQL e contra o valor total e não parcial (por exemplo, LIKE 'value%')... ao capturar os dados de pesquisa, criptografe esses dados usando o mesmo algoritmo usado quando os dados foram criptografados e pesquise por isso.
Por exemplo:
O que teria sido:
Em vez disso, pode parecer: