terça-feira, 23 de fevereiro de 2010

Usando MD5 em python

Olá,

muitos já devem conhecer o algoritmo md5, utilizado amplamente em transferencias de arquivos, pois ele efetua um teste de intefridade dos dados.
Ele funciona mais ou menos da seguinte forma: analisa os dados e gera um número único de 128 bits(esse número pode variar conforme o software ou algoritmo que utilizar).
Então a melhor forma(e praticamente única) é testar dois arquivos e analisar seus códigos MD5, se forem iguais é porque os dois arquivos são exatamente iguais ( e quando digo exatamente é porque é, pois a mínima diferença, por menor que seja, gera dois códigos diferentes).

Em python existe um módulo MD5, chamado de ...md5 (sinistro...=P)
Para importar basta digitar no interpretador python:


>>> import md5


Não se preocupe, o md5 é um módulo built-in.

Para gerar o código:


>>> md5.new("string para teste").hexdigest()
'a16ee9e06b3d8f40a5d5d2dc7d88074a'
>>> var = 1
>>> md5.new("%s" % var)
'c4ca4238a0b923820dcc509a6f75849b'
>>> arquivo = open('[arquivo_a_ser_comparado]', 'r').read()
>>> md5.new(arquivo).hexdigest()
'valor_depende_do_arquivo'


Apartir do python 2.5 um novo módulo comessou a ser utilizado, o hashlib, deixando de lado o md5 ( mas ele ainda está presente nas versões superiores, mas com um alerta de preterido).
Uma vantagem do módulo hashlib (além de estar com suporte ativo) é que pode-se obter números de checagem de até 512 bits.
As opções de tamanho de chave são: sha224 para 224 bits, sha256 para 256 bits, sha384 para 384 bits, sha512 para 512 bits e o antigo md5, para 128 bits.


>>> hashlib.sha244('string ou buffer de leitura') #224 bits
>>> hashlib.sha256('string ou buffer de leitura') #256 bits
>>> hashlib.sha384('string ou buffer de leitura') #384 bits
>>> hashlib.sha512('string ou buffer de leitura') #512 bits
>>> hashlib.md5('string ou buffer de leitura') #128 bits


Um exemplo de uso, para quem estiver iniciando em python:
case: se dois arquivos forem identicos, exclua um(em linux):

>>> import hashlib
>>> import os
>>> path_arquivo_1 = '[path].arquivo'
>>> path_arquivo_2 = '[path].arquivo'
>>> arquivo_1 = open(path_arquivo_1).read()
>>> arquivo_2 = open(path_arquivo_2).read()
>>> if hashlib.sha512(arquivo_1) == hashlib.sha512(arquivo_2):
...     print "Excluindo %s, pois ja existe outro arquivo igual a esse." % path_arquivo_2
...     os.system('rm %s' % path_arquivo_2)
... else:
...     print "Os arquivos São diferentes"


É isso aí pessoal, qualquer dúvida, consultar a documentação do python ou perguntar nos comentários.


2 comentários:

  1. Cley Randal
    Bom post o seu, objetivo e útil.

    Já havia conseguido o hash de um arquivo de texto olhando na documentação do python e fazendo +ou- o que você fez acima.

    O problema foi quando fui testar em um arquivo ISO de DVD de 4,1 GB. Acho que ele não consegue carregar o arquivo todo dessa forma.

    As tentativas abaixo falharam:
    //como binário
    open(vArquivo, 'rb').read()
    //como texto (de forma explicita)
    open(vArquivo, 'rt').read()

    O módulo hashlib só aceita string (texto) ou buffer (não sei o que é buffer nesse contexto).

    Talvez teria que abrir o arquivo como buffer, só não sei como.

    Se alguém conseguir o hash de arquivos grandes usando só python, mandem a referência ou o material pro meus e-mail.

    Obrigado pessoal.

    ResponderExcluir
  2. cara eu estou com um problema para criar um sistema de login. Eu criei um sistema de cadastros, esse sistema pega o campo senha e aplica o algorítimo md5 e quando clicar no botão cadastrar ele salva no banco de dados. Ai para fazer o login eu pego o que o usuário digitou no campo senha uso o md5 e comparo com o que foi salvo no banco. o problema é que quando eu uso o md5 no menu login no campo senha o algorítimo gera outro código diferente mesmo sendo digitado a mesma coisa na hora de cadastrar e na hora de fazer o login.

    ResponderExcluir