Muita confusão se faz quanto aos algoritmos de HASH. Muitos acham que ele é um algoritmo de criptografia. Não é. Pertence a ciência da criptografia, alguns são até baseados em algoritmos de criptografia, mas o que quero deixar claro é que Algoritmos de HASH não servem para cifrar.
HASH são também conhecidos como "algoritmos de mão única". Qualquer coisa que se "cifra" com eles é impossível matematicamente de se recuperar. Além disso eles possuem outras características:
a) não possuem chave. Gerar o hash não envolve nenhum segredo que deva ser compartilhado.
b) tamanho único. Não importa o quão grande é a informação original, o hash será sempre de um mesmo tamanho. Como exemplo o famoso e depreciado MD5. Ele tem 128 bits de tamanho, mesmo que seja o HASH de uma única letra (8bits) ou de um arquivo de 1GB!
c) infinitos hashes para uma mesma mensagem. Isto é meio confuso de entender e pode até parecer uma fraqueza. Novamente o caso do MD5: como ele possui sempre 128 bits, o número de hashes MD5 existentes no Universo é grande, mas limitado e conhecido. É 2
128. Contudo o número de mensagens é infinito. Não tem hashes únicos para cada diferente mensagem no Universo. Logo, tem mensagens que possuem o mesmo HASH. Se o HASH da frase "Eu sou Viva o
Linux" tiver como HASH FE:45:56, existem outras infinitas mensagens que gerem o mesmo hash FE:45:56. Isto vale para qualquer algoritmo de hash e não significa uma fraqueza, apenas uma conclusão matemática. Descobrir duas ou mais mensagens que geram o mesmo hash é chamado de colisão, coisa que o pessoal de Banco de Dados estuda (porque se usa hash como método de pesquisa em BD).
Para tornar mais fácil entender o que é um algoritmo de HASH eu costumo apresentar em sala de aula o "HASH by Elgio". Um HASH podre, fraco, mas fácil de entender.
Meu algoritmo de HASH consiste em simplesmente somar os bytes de uma frase, com teto de 255 (255 +2 = 257 = 2). Matematicamente pode-se expressar como o Modulo 256 da soma de todos os bytes. Depois de somar todos os caracteres o byte final é considerado o hash.
Na frase "Viva o Linux" tem-se os seguintes bytes:
'V' 'i' 'v' 'a' ' ' 'o' ' ' 'L' 'i' 'n' 'u' 'x'
086 105 118 097 032 111 032 076 105 110 117 120
Soma dos bytes = 1109
1109 mod 256 = 85
Neste caso o Hash de "Viva o Linux" através do algoritmo "by Elgio" seria 85. Veja que pelo meu método não importa o tamanho da frase, o HASH será sempre um número entre 0 e 255. Isto serve para explicar a propriedade que eu citei de que o hash é sempre do mesmo tamanho.
Mas a grande pergunta é para que serve isto (não este meu algoritmo que só serve para fins didáticos).
Se eu previamente conheço o HASH (85) e alguém me apresenta a frase "Grande Linux" dizendo que ela é do hash armazenado, ao verificar eu percebo que a frase fornecida possui o HASH 129. Como não é 85, esta frase não é deste hash.
A grande sacada do arquivo de senhas do Linux é armazenar apenas o HASH. Se minha senha fosse "Viva o Linux" o arquivo de senhas teria apenas 85. Se eu digitar corretamente a senha o SO deverá calcular os mesmos 85 o que indica que acertei a senha. Assim o sistema não precisa armazenar a senha, mas somente o HASH.
Não se apressem em falar mal deste meu HASH by Elgio! Ele é ruim mesmo e é bom que seja para meus fins didáticos.
O problema é que com este meu algoritmo de HASH ridículo é muito fácil alguém, até com papel e lápis, chegar aos mesmos 85 sem saber a frase. De cara eu percebo que apenas a letra 'U' já resolve meu problema pois ela é justamente 85. Apresentei este algoritmos by Elgio para explicar o que é HASH, mas não como exemplo de um que possa ser usado. Ele não resiste ao mais simples ataque: o da força bruta.
Um algoritmo de HASH sério precisa fazer exatamente isto, reduzir cadeias de bytes para uma sequência menor de tamanho reduzido, mas sem que alguém tenha meios de quebrar.
O MD5 é bom nisto. Como seus 128 bits, um ataque de força bruta poderia levar até 2
128 possibilidades (um cara muito azarado).
Considerando que não existem caras tão azarados de acertar justamente na última tentativa, trabalhar com a metade é uma boa medida.
Qual a metade de 2
128?
NÃO NÃO!!
Não é 2
64
A metade de 2
128 é 2
127!
Isto ainda dá 170141183460469231731687303715884105728 possibilidades! (Você consegue ler este número? )
Vamos a uma simulação: se eu tiver 5.000.000 de computadores, cada um deles com 100.000 processadores de 100Ghz que consiga a façanha de realizar uma tentativa por ciclo de clock (100G tentativas por segundo), o tempo estimado para quebrar seria:
170141183460469231731687303715884105728 / 100.000.000.000 / 100.000 / 5.000.000
Dividi por 100 bilhões porque é quantas tentativas um processador completa por segundo (100Ghz), dividi por 100.000 porque cada computador tem cem mil processadores e dividi novamente por 5.000.000 porque tenho cinco milhões de computadores iguais a este.
Ainda assim isto resulta em 3.402.823.669.209.384 segundos ou 107.902.830 anos! Bem vindo a força da matemática da força bruta. Novamente, aos já iniciados em criptografia, estou falando de força bruta sendo que bem sabemos que existem atalhos em alguns métodos.
Resumindo: existem algoritmos de HASH que são impossíveis de se quebrar por força bruta. MD5 ainda é um exemplo deles (as vulnerabilidades descobertas no MD5 tem ver com colisões não com força bruta).
Tais algoritmos podem ser usados para nosso propósito e de fato o são!