Escolhendo o algoritmo correto na função HashBytes

20

Precisamos criar o valor de hash dos dados nvarchar para fins de comparação. Existem vários algoritmos de hash disponíveis no T-SQL, mas qual é o melhor para escolher nesse cenário?

Queremos garantir que o risco de ter um valor de hash duplicado para dois valores diferentes de nvarchar seja o mínimo. Com base na minha pesquisa na internet, o MD5 parece o melhor. Isso esta certo? O MSDN nos informa (link abaixo) sobre os algoritmos disponíveis, mas nenhuma descrição sobre qual para quais condições?

HASHBYTES (Transact-SQL)

Precisamos juntar duas tabelas em duas colunas nvarchar (max). Como você pode imaginar, a consulta leva muito tempo para ser executada. Pensamos que seria melhor manter o valor de hash de cada dado nvarchar (max) e fazer a junção nos valores de hash, em vez dos valores nvarchar (max) que são blobs. A questão é qual algoritmo de hash fornece a exclusividade, para que não corramos o risco de ter um valor de hash para mais de um nvarchar (max).

Céu
fonte

Respostas:

18

A HASHBYTESfunção ocupa apenas 8000 bytes como entrada. Porque suas entradas são potencialmente maiores do que isso, duplica na faixa do campo que fica hash irá causar colisões, independentemente do algoritmo escolhido. Considere com cuidado o intervalo de dados que planeja fazer hash - o uso dos primeiros 4000 caracteres é a escolha óbvia , mas pode não ser a melhor opção para seus dados.

De qualquer forma, devido ao que é uma função hash, mesmo que as entradas tenham 8000 bytes ou menos, a única maneira de garantir 100% de correção nos resultados é comparar os valores base em algum momento (leia-se: não necessariamente primeiro ). Período.

A empresa determinará se é necessária 100% de precisão. Isso informará que (a) a comparação dos valores base é necessária ou (b) você deve considerar não comparar os valores base - quanta precisão deve ser trocada pelo desempenho.

Embora colisões de hash sejam possíveis em um conjunto de entradas exclusivo, elas são infinitesimalmente raras, independentemente do algoritmo escolhido. A ideia geral de usar um valor de hash nesse cenário é restringir eficientemente os resultados da junção a um conjunto mais gerenciável, para não necessariamente chegar ao conjunto final de resultados imediatamente. Novamente, para 100% de precisão, essa não pode ser a etapa final do processo. Esse cenário não está usando hash para fins de criptografia, portanto, um algoritmo como o MD5 funcionará bem.

Seria extremamente difícil para mim justificar a mudança para um algoritmo SHA-x para fins de "precisão", porque, se a empresa estiver enlouquecendo com as minúsculas possibilidades de colisão do MD5, é provável que ela também esteja enlouquecida. os algoritmos SHA-x também não são perfeitos. Eles precisam aceitar a pequena imprecisão ou exigir que a consulta seja 100% precisa e viva com as implicações técnicas associadas. Suponho que se o CEO dorme melhor à noite sabendo que você usou SHA-x em vez de MD5, tudo bem; ainda não significa muito do ponto de vista técnico neste caso.

Falando em desempenho, se as tabelas forem lidas principalmente e o resultado da junção for necessário com frequência, considere implementar uma exibição indexada para eliminar a necessidade de calcular a junção inteira toda vez que solicitada. É claro que você troca o armazenamento por isso, mas pode valer a pena pela melhoria no desempenho, principalmente se for necessária uma precisão de 100%.

Para uma leitura mais aprofundada sobre a indexação de valores de cadeia longa, publiquei um artigo que mostra um exemplo de como fazer isso para uma única tabela e apresenta coisas a serem consideradas ao tentar o cenário completo nesta pergunta.

Jon Seigel
fonte
8

O MD5 deve estar bom e a saída pode ser armazenada em um binário (16). A probabilidade de uma colisão (veja o paradoxo do aniversário ) ainda é muito baixa, mesmo com um grande tamanho de amostra física. A saída do SHA-1 leva 20 bytes e a saída do SHA-256 leva 32 bytes. A menos que você tenha um número tão grande de registros que a probabilidade de colisão de seu aniversário se torne significativa (fisicamente impossível ou pelo menos impraticável com as tecnologias de hardware atuais), provavelmente estará OK.

ConcernedOfTunbridgeWells
fonte
0

Eu não vi isso mencionado nas respostas, mas por MSDN :

A partir do SQL Server 2016 (13.x), todos os algoritmos que não sejam SHA2_256 e SHA2_512 foram descontinuados. Algoritmos mais antigos (não recomendados) continuarão funcionando, mas irão gerar um evento de reprovação.

Fiz uma pergunta semelhante; portanto, cabe a você se você deseja usar uma função descontinuada, como o MD5 (se você tiver mais de 2016). Você pode fazer testes para ver quanta diferença há em armazenamento e desempenho entre MD5 e SHA2.

Gabe
fonte