HOWTO · Python

Python Checksum

Aprenda a gerar um checksum de arquivo com hashlib e compará-lo com um resumo SHA-256 confiável.

Nesta página

Um checksum de arquivo é um resumo compacto calculado a partir dos bytes do arquivo. Você pode calculá-lo depois de baixar um arquivo e compará-lo com um resumo publicado por um canal confiável. Uma correspondência ajuda a detectar alterações acidentais ou corrupção, mas não comprova, por si só, quem criou o arquivo: um invasor capaz de substituir tanto o arquivo quanto o resumo de referência pode fazer com que os dois correspondam.

O módulo hashlib do Python oferece algoritmos de hash padrão. O processo é determinístico: os mesmos bytes e o mesmo algoritmo produzem o mesmo resumo, enquanto a alteração de um único byte normalmente muda o resultado. Um checksum descreve os bytes, não o nome nem o formato do arquivo.

O que um checksum de arquivo pode revelar

Um checksum pode ajudar a verificar se uma cópia ainda contém o conteúdo esperado. O valor esperado deve vir de uma fonte confiável, como uma página de lançamento autenticada por um canal separado. Comparar dois valores baixados do mesmo local não confiável oferece pouca segurança. Para decisões de segurança, use um hash criptográfico moderno, como SHA-256, e verifique separadamente a origem do valor de referência.

Gerar um checksum com hashlib

Abra o arquivo em modo binário para que o Python calcule o hash dos bytes exatos, sem decodificar texto nem converter quebras de linha. Leia o arquivo em blocos e passe cada bloco ao método update() do objeto de hash. Assim, o uso de memória permanece limitado mesmo quando o arquivo é muito maior do que a memória disponível. hexdigest() retorna texto hexadecimal legível; digest() retorna o mesmo resumo como bytes compactados.

Execute este exemplo. Os rótulos exibidos na saída permanecem em inglês.

import hashlib
from pathlib import Path
from tempfile import TemporaryDirectory


def sha256_file(path):
    digest = hashlib.sha256()
    with open(path, "rb") as file:
        for chunk in iter(lambda: file.read(64 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()


with TemporaryDirectory() as directory:
    path = Path(directory) / "sample.bin"
    path.write_bytes(b"abc")
    expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
    actual = sha256_file(path)
    print(f"SHA-256: {actual}")
    print(f"Matches trusted value: {actual == expected}")
SHA-256: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
Matches trusted value: True

O código cria um pequeno arquivo de exemplo para poder ser executado como está; no seu script, substitua path pelo caminho do arquivo baixado. Para um arquivo baixado, defina path com a localização dele e compare o resumo resultante com uma referência confiável para esse arquivo.

Verificar um arquivo com um checksum confiável

Armazene ou obtenha o resumo esperado de forma independente e, em seguida, compare-o com o valor retornado por sha256_file. A comparação booleana do exemplo é verdadeira quando as duas strings hexadecimais coincidem. Um resultado falso significa que o arquivo não corresponde à referência; ele pode ter sido corrompido, alterado intencionalmente ou associado à referência errada. Baixe-o novamente ou investigue a origem, em vez de tratar a divergência como prova de uma causa específica.

Em fluxos de trabalho sensíveis à segurança, normalize a string esperada somente conforme o formato documentado por quem a publicou e, depois, compare o resumo completo. Não compare apenas um prefixo curto quando o resumo completo estiver disponível. Uma comparação bem-sucedida confirma que os bytes correspondem à referência confiável representada pelo resumo esperado; ela não autentica quem publicou o arquivo, a menos que a própria referência seja autenticada.

Lidar com arquivos grandes e erros comuns

A leitura em blocos evita carregar o arquivo inteiro na memória. O tamanho escolhido para cada bloco afeta a eficiência de entrada e saída, mas não o resumo resultante, desde que cada byte seja lido uma vez e na ordem correta. O modo binário é importante porque o modo de texto pode decodificar dados ou converter quebras de linha. Mantenha o arquivo aberto somente durante a leitura, como faz a instrução with.

Evite ler todos os bytes de uma só vez com file.read() quando o arquivo for muito grande. Confira também se o caminho aponta para o arquivo que você pretende verificar e se o algoritmo usado para calcular o valor de referência é o mesmo usado localmente. Um erro de digitação ou a diferença entre algoritmos produz strings distintas, mesmo quando o conteúdo do arquivo não mudou. Se o arquivo for alterado durante o cálculo, o resumo pode representar uma mistura do conteúdo; use uma cópia estável quando outro processo puder estar gravando nele.

Escolher um algoritmo de hash e entender seus limites

Use SHA-256 para calcular um resumo de arquivo de uso geral quando uma fonte confiável fornecer uma referência SHA-256. O nome do algoritmo está disponível por meio de hashlib.sha256(). MD5 ainda aparece em alguns exemplos antigos e fluxos de compatibilidade, mas é vulnerável a ataques de colisão e não serve para verificações de integridade sensíveis à segurança. Não use MD5 para comprovar autenticidade nem para se proteger contra um invasor deliberado.

Checksums também são diferentes de hashes de senhas: um resumo rápido é adequado para comparar arquivos, enquanto senhas exigem esquemas próprios de hash com salt. Em qualquer caso, o resumo só pode indicar se os bytes correspondem a um valor de referência. A confiança depende de como essa referência foi obtida e protegida.