segunda-feira, 4 de março de 2013

Calculando o valor hash de um arquivo

Em um post anterior calculamos o CRC de um arquivo. Como disse antes o CRC não é um método para garantir a segurança da mensagem (no caso do arquivo). Neste post vamos ver como criar um hash para um arquivo.

Uma função hash é basicamente um algoritmo que recebe um bloco de dados (no nosso caso um array de bytes que contem o conteúdo do arquivo) e retorna uma seqüência de bits de tamanho fixo de tal forma que qualquer alteração dos dados irá alterar o valor de hash.

Os dados a serem codificados são muitas vezes chamado de "mensagem" daí a razão de encontrarmos em Java como uma classe MessageDigest. O resultado da função hash é chamado valor hash, message digest ou digest. É por esta razão que a geração do hash em Java termina com a chamada do método digest().


A função hash ideal tem quatro propriedades principais:

  • é fácil de calcular o valor de hash para qualquer mensagem
  • é impossível gerar uma mensagem que tem um hash dado (não dá para transformar o hash na mensagem original)
  • é inviável para modificar uma mensagem sem alterar o hash
  • é praticamente impossível encontrar duas mensagens diferentes com o mesmo hash (isto é chamado de collision resistance)


Com estas pré-condições podemos ver que um hash autentica uma mensagem e é por isto que queremos saber como utilizar este tipo de "coisa".

Temos diversos algoritmos para calculo de hash. Neste post vamos ver como gerar dois dos mais usados.:

  • MD5 - você pode ler mais na RFC 1321 que define o Message-Digest algorithm  e
  • SHA que vem de "secure hash algorithm". Existem variações de SHA, denominadas SHA-0, SHA-1 e SHA-2. Mais comumente iremos encontrar SHA-1 (que gera digests de 160 bits) e SHA-2 com 224, 256, 384 e 512 bits. Hoje em função da capacidade computacional dos equipamentos atuais é recomendável utilizar no mínimo 256 bits. Já existe SHA-3 porém é relativamente novo e não vamos ver como gerá-lo aqui. Para quem quer conhecer mais recomendo a leitura das RFC 3174 que descreve SHA-1 e RFC 6234 que descreve SHA-2.

A teoria é bastante complicada e não vamos entrar nela aqui. Um bom livro é Applied Cryptography, Second Edition: Protocols, Algorthms, and Source Code in C de Bruce Schneier.

Vamos ao nosso código. Para gerar um hash em Java é bastante simples. Precisamos somente da classe java.security.MessageDigest e podemos gerar um hash com três passos:
  1. obtemos um objeto chamando MessageDigest.getInstance(nome do algoritmo que queremos)
  2. chamamos o método update(byte[])
  3. chamamos o método digest() que retorna o hash como um array de bytes
Como queremos ter o hash em um formato apresentável, acrescentei na nossa classe um método converteByteArrayToString que recebe o array de bytes e retorna uma String com a sequência em hexadecimal do valor hash.

Vamos rodar nosso exemplo:

Foi gerado o valor hash com SHA-256. Para calcular SHA-512 basta trocar o nome do algoritmo:

Para MD5 é igual:

Ok. Ficamos assim por hoje....

Nenhum comentário:

Postar um comentário