O artigo da Wikipedia sobre funções de hash é muito bom, mas eu darei aqui minha opinião.
O que é um hash?
"Hash" é realmente um termo amplo, com diferentes significados formais em diferentes contextos. Não existe uma única resposta perfeita para sua pergunta. Vou explicar o conceito geral subjacente e mencionar alguns dos usos mais comuns do termo.
Um "hash" é uma função denominada função de hash
que recebe como objetos de entrada e gera uma string ou número. Os objetos de entrada geralmente são membros de tipos de dados básicos, como seqüências de caracteres, números inteiros ou maiores compostos por outros objetos, como estruturas definidas pelo usuário. A saída é tipicamente um número ou uma sequência. O substantivo "hash" geralmente se refere a essa saída. O verbo "hash" geralmente significa "aplicar uma função hash". As principais propriedades que uma função hash deve ter são:h
- Deve ser fácil calcular e
- As saídas devem ser relativamente pequenas.
Exemplo:
Digamos que queremos números de hash no intervalo de 0 a 999.999.999 para numerar entre 0 e 99. Uma função simples de hash pode ser .h ( x ) = xmod100
Propriedades adicionais comuns:
Dependendo do caso de uso, podemos desejar que a função hash satisfaça propriedades adicionais. Aqui estão algumas propriedades adicionais comuns:
Uniformidade : Muitas vezes queremos que os hashes dos objetos sejam distintos. Além disso, podemos querer que os hashes sejam "espalhados". Se eu quiser misturar alguns objetos em 100 buckets (para que a saída da minha função hash seja um número de 0 a 99), normalmente espero que cerca de 1/100 de objetos cheguem ao balde 0, e cerca de 1/100 balde 1 e assim por diante.
Resistência à colisão criptográfica : Às vezes, isso é levado ainda mais longe, por exemplo, na criptografia, eu posso querer uma função hash de modo que seja computacionalmente difícil para um adversário encontrar duas entradas diferentes que mapeiam a mesma saída.
Compactação : muitas vezes eu quero misturar entradas arbitrariamente grandes em uma saída de tamanho constante ou em um número fixo de buckets.
Determinismo : talvez eu queira uma função hash cuja saída não mude entre as execuções, ou seja, a saída da função hash no mesmo objeto permanecerá sempre a mesma. Isso pode parecer conflitar com a uniformidade acima, mas uma solução é escolher a função hash aleatoriamente uma vez e não alterá-la entre as execuções.
Algumas aplicações
Um aplicativo comum está em estruturas de dados, como uma tabela de hash, que são uma maneira de implementar dicionários. Aqui, você aloca um pouco de memória, digamos, 100 "baldes"; quando solicitado a armazenar um par (chave, valor) no dicionário, você hash a chave em um número de 0 a 99 e armazene o par no intervalo correspondente na memória. Em seguida, quando você for solicitado a procurar uma chave, faça o hash da chave em um número de 0 a 99 com a mesma função de hash e verifique o balde para ver se essa chave está lá. Nesse caso, você retorna seu valor.
Observe que você também pode implementar dicionários de outras maneiras, como em uma árvore de pesquisa binária (se seus objetos forem comparáveis).
Outra aplicação prática são as somas de verificação, que são maneiras de verificar se dois arquivos são iguais (por exemplo, o arquivo não foi corrompido em sua versão anterior). Como é improvável que as funções de hash mapeiem duas entradas para a mesma saída, você calcula e armazena um hash do primeiro arquivo, geralmente representado como uma string. Esse hash é muito pequeno, talvez apenas algumas dezenas de caracteres ASCII. Então, quando você obtém o segundo arquivo, faz o hash e verifica se a saída é a mesma. Nesse caso, quase certamente é exatamente o mesmo arquivo, byte por byte.
Outra aplicação é na criptografia, onde esses hashes devem ser difíceis de "inverter" - ou seja, dada a saída e a função hash, deve ser computacionalmente difícil descobrir as entradas que levaram a essa saída. Um uso disso é para senhas: em vez de armazenar a senha em si, você armazena um hash criptográfico da senha (talvez com alguns outros ingredientes). Em seguida, quando um usuário digita uma senha, você calcula seu hash e verifica se ele corresponde ao hash correto; Nesse caso, você diz que a senha está correta. (Agora, mesmo alguém que pode procurar e descobrir o hash salvo no servidor não fica tão fácil fingir ser o usuário.) Esse aplicativo pode ser um caso em que a saída seja tão longa ou mais longa que a entrada, pois a entrada é tão curta.