hashlib no Python: hashes seguros

Publicado em: 19/08/2026
Tempo de leitura: 6 minutos
Leitor de impressão digital representando verificação de hashes com hashlib no Python

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.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Desenvolvedor configurando servidor HTTPS e certificado TLS com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crie servidor HTTPS local no Python

    Aprenda HTTPSServer no Python para servir HTTPS localmente, configurar certificados, usar threads e entender limites de segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    08/10/2026
    Arquivos protegidos representando extração segura de TAR com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extraia TAR com segurança

    Aprenda tarfile extraction_filter no Python para extrair arquivos TAR com validação, segurança e controle de caminhos.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026
    Código Python exibindo avisos controlados com catch_warnings
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    catch_warnings: capture warnings em testes Python

    Aprenda catch_warnings no Python para capturar, testar e controlar avisos com filtros específicos e segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código Python representando referências persistentes do pickle
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pickle persistent_id: serialize referências externas

    Aprenda pickle persistent_id no Python para serializar referências externas com IDs estáveis, validação, segurança e compatibilidade.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código binário representando buffers e memória no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    memoryview.count: conte valores sem copiar buffers

    Aprenda memoryview.count no Python para contar bytes e valores em buffers sem cópias, com formatos, limites e boas práticas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026
    Código Python com anotações de tipos
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib: evite imports circulares em anotações

    Aprenda annotationlib no Python para ler anotações adiadas, evitar imports circulares e criar ferramentas de introspecção seguras.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026