O módulo hashlib oferece uma interface padronizada para funções hash criptográficas como SHA-256, SHA-512, SHA-3 e BLAKE2. Um hash transforma dados de tamanho arbitrário em um resumo de tamanho fixo. Pequenas mudanças na entrada produzem resultados muito diferentes, o que torna esses resumos úteis para verificar integridade, identificar conteúdo, deduplicar arquivos e construir protocolos de autenticação.
Apesar do nome “hash seguro”, escolher o algoritmo e o contexto corretos é essencial. SHA-256 pode verificar um download, mas não é suficiente para armazenar senhas. Um hash sem chave também não prova quem gerou a mensagem. Este guia mostra as APIs principais, processamento incremental, arquivos grandes, comparação segura, SHAKE, BLAKE2, PBKDF2 e scrypt.
Como um hash funciona
Uma função hash recebe bytes e produz um digest. A mesma entrada sempre gera a mesma saída. Não existe uma operação normal de “descriptografar” o hash para recuperar a mensagem. Porém, entradas previsíveis, como senhas comuns, podem ser testadas por força bruta. Por isso, irreversibilidade não significa proteção automática.
O primeiro passo é converter texto em bytes:
import hashlib
message = "Academify".encode("utf-8")
digest = hashlib.sha256(message)
print(digest.digest())
print(digest.hexdigest())
digest() devolve bytes binários. hexdigest() devolve texto hexadecimal, mais conveniente para bancos, manifests e logs. Para compreender a relação entre bytes e hexadecimal, consulte o guia de binascii no Python.
Qual algoritmo escolher?
Para novos sistemas, SHA-256 costuma ser uma escolha segura e interoperável para integridade. SHA-512 pode ser útil em protocolos que o especificam. SHA-3 é uma família com construção diferente da SHA-2. BLAKE2 é rápido, configurável e oferece modo com chave. SHAKE produz digests de comprimento variável.
MD5 e SHA-1 têm fraquezas de colisão conhecidas. Eles ainda aparecem em formatos legados e identificadores não adversariais, mas não devem proteger assinaturas, certificados ou conteúdo que um atacante possa manipular. O argumento usedforsecurity=False existe para indicar explicitamente um uso não relacionado à segurança em ambientes restritos; ele não torna o algoritmo mais forte.
print(sorted(hashlib.algorithms_guaranteed))
print("sha256" in hashlib.algorithms_available)
algorithms_guaranteed lista os algoritmos portáveis da biblioteca. algorithms_available depende também do OpenSSL usado pela instalação.
Atualização incremental
Você não precisa carregar todo o conteúdo na memória. Chamadas repetidas a update() são equivalentes ao hash da concatenação.
hasher = hashlib.sha256()
hasher.update(b"parte 1")
hasher.update(b"parte 2")
print(hasher.hexdigest())
Esse padrão é ideal para arquivos grandes, uploads e streams. Ele se relaciona diretamente às técnicas do artigo sobre leitura de arquivos gigantes.
Verificar um arquivo com SHA-256
from pathlib import Path
import hashlib
def sha256_file(path: Path, chunk_size: int = 1024 * 1024) -> str:
hasher = hashlib.sha256()
with path.open("rb") as file:
while chunk := file.read(chunk_size):
hasher.update(chunk)
return hasher.hexdigest()
print(sha256_file(Path("pacote.zip")))
Compare o resultado com um valor obtido por um canal confiável. Se o arquivo e o hash vierem do mesmo servidor comprometido, a comparação não prova autenticidade. Para downloads, publique o digest por HTTPS e, quando o risco justificar, use uma assinatura digital.
Arquivos compactados também podem conter checksums internos, mas eles normalmente detectam corrupção acidental. Veja o guia para criar ZIP com Python e diferencie CRC de hash criptográfico.
hashlib.file_digest()
Desde Python 3.11, file_digest() simplifica o hash de um arquivo binário e pode usar caminhos de I/O otimizados.
with open("pacote.zip", "rb") as file:
digest = hashlib.file_digest(file, "sha256")
print(digest.hexdigest())
Depois da chamada, considere a posição e o estado do arquivo desconhecidos e feche-o normalmente. No Python 3.14, um arquivo em modo não bloqueante gera BlockingIOError; versões anteriores podiam produzir um digest incorreto com bytes nulos espúrios.
Comparar digests corretamente
Para uma verificação simples de arquivo, uma comparação comum costuma ser suficiente. Em autenticação e segredos, use hmac.compare_digest(), que reduz vazamentos de tempo relacionados ao ponto da primeira diferença.
import hmac
expected = "a" * 64
calculated = sha256_file(Path("pacote.zip"))
if not hmac.compare_digest(expected, calculated):
raise ValueError("Arquivo não corresponde ao digest esperado")
Uma comparação constante não corrige um protocolo mal projetado. O valor esperado ainda precisa ser autêntico e o algoritmo deve ser adequado.
SHAKE com tamanho variável
shake_128 e shake_256 exigem que você informe o número de bytes do resultado.
token_id = hashlib.shake_256(b"registro-123").hexdigest(20)
print(token_id) # 40 caracteres hexadecimais
Defina o tamanho com base na segurança e na probabilidade de colisão exigidas. Não encurte digests arbitrariamente em identificadores expostos a entrada adversarial.
BLAKE2 e personalização
BLAKE2b é otimizado para plataformas de 64 bits e permite resultados de 1 a 64 bytes. BLAKE2s produz até 32 bytes e é adequado a plataformas menores. O parâmetro person separa domínios: a mesma entrada usada para finalidades diferentes gera digests diferentes.
file_hash = hashlib.blake2b(
b"conteudo",
digest_size=32,
person=b"Files-v1",
).hexdigest()
block_hash = hashlib.blake2b(
b"conteudo",
digest_size=32,
person=b"Blocks-v1",
).hexdigest()
assert file_hash != block_hash
BLAKE2 também possui modo com chave, útil para autenticação de mensagens. Ainda assim, HMAC é mais conhecido e costuma ser preferível quando interoperabilidade e revisão de segurança são prioridades.
Senhas: por que SHA-256 sozinho é errado?
Hashes gerais são rápidos. Essa característica é ótima para arquivos, mas permite que atacantes testem milhões de senhas por segundo. Para credenciais, use Argon2id, scrypt, bcrypt ou PBKDF2 com salt aleatório e custo calibrado.
O artigo sobre hash de senhas em Python explica o fluxo completo. Não reutilize exemplos de SHA-256 puro para autenticação.
PBKDF2 com salt
import os
import hashlib
import hmac
salt = os.urandom(16)
iterations = 600_000
password = "senha longa".encode("utf-8")
derived = hashlib.pbkdf2_hmac(
"sha256",
password,
salt,
iterations,
)
# Armazene algoritmo, iterações, salt e derived.
O número ideal de iterações depende do hardware e precisa ser medido. A autenticação deve ser lenta o suficiente para dificultar ataques, mas aceitável para usuários. Imponha limite ao tamanho da senha antes de executar a derivação.
scrypt e custo de memória
hashlib.scrypt() adiciona custo de memória, dificultando paralelização em hardware especializado.
derived = hashlib.scrypt(
password,
salt=salt,
n=2**14,
r=8,
p=1,
dklen=32,
)
Os parâmetros devem ser calibrados e armazenados junto ao hash. Trate ValueError e erros de memória como falhas controladas, sem reduzir silenciosamente a segurança.
Hashes para deduplicação e cache
Um digest pode identificar conteúdo em caches e pipelines. Inclua no hash todas as opções que afetam o resultado para evitar colisões semânticas.
def cache_key(url: str, language: str) -> str:
canonical = f"v1\n{language}\n{url}".encode("utf-8")
return hashlib.sha256(canonical).hexdigest()
Ao integrar APIs, normalize cuidadosamente a entrada e nunca use um hash para esconder segredos. O guia de consumo de APIs REST mostra práticas de validação e transporte.
Erros comuns
Os erros mais frequentes são passar str sem codificar, usar MD5 ou SHA-1 em segurança, confundir hash com criptografia, usar SHA-256 puro para senhas, comparar MACs com ==, confiar em um digest recebido pelo mesmo canal inseguro e carregar arquivos enormes na memória.
Boas práticas
Use SHA-256 ou algoritmo moderno definido pelo protocolo. Processe dados em blocos. Registre o nome e a versão do esquema junto ao digest. Separe integridade de autenticidade. Use HMAC ou assinatura quando precisar provar origem. Para senhas, use uma KDF lenta com salt e parâmetros armazenados. Nunca invente uma construção criptográfica própria.
Conclusão
hashlib cobre desde hashes simples de arquivos até SHA-3, SHAKE, BLAKE2, PBKDF2 e scrypt. O módulo é fácil de usar, mas o contexto determina a segurança. Um digest pode detectar alterações; uma mensagem autenticada precisa de chave; uma senha precisa de derivação lenta; e um download confiável precisa de um valor esperado obtido com autenticidade.
Consulte a documentação oficial de hashlib e a publicação FIPS 180-4 do NIST.







