SHA-256 em Python — hashlib e exemplos de código

·DevOps Engineer & Python Automation Specialist·Revisado porMaria Santos·Publicado

Use o Gerador de Hash SHA-256 gratuito diretamente no seu navegador — sem instalação.

Experimentar Gerador de Hash SHA-256 online →

Todo pipeline de deploy que já construí precisou, em algum momento, verificar o checksum de um arquivo, assinar um payload de webhook ou criar uma impressão digital de chave de cache. O hashing SHA-256 em Python com o módulo embutido hashlib resolve todos esses casos — e você já o tem instalado. hashlib.sha256() encapsula a implementação do OpenSSL no CPython, portanto é rápido e compatível com FIPS por padrão. Para um hash rápido sem escrever código, o gerador SHA-256 online entrega o resultado instantaneamente. Todos os exemplos são para Python 3.9+.

  • hashlib.sha256(data).hexdigest() é a forma padrão de calcular o hash de bytes — parte da stdlib, apoiado pelo OpenSSL.
  • Strings devem ser codificadas em bytes primeiro: hashlib.sha256("texto".encode("utf-8")).
  • Para checksums de arquivos, alimente partes via .update() — nunca carregue um arquivo grande inteiro na memória.
  • HMAC-SHA256 requer o módulo hmac: hmac.new(key, msg, hashlib.sha256) — o SHA-256 sozinho não possui chave.

O que é o hash SHA-256?

SHA-256 (Secure Hash Algorithm, 256 bits) recebe uma entrada de comprimento arbitrário e produz um digest fixo de 256 bits (32 bytes). A mesma entrada sempre gera a mesma saída, mas mesmo uma única alteração de bit na entrada produz um hash completamente diferente — essa propriedade é chamada de efeito avalanche. SHA-256 faz parte da família SHA-2, padronizada pelo NIST, e é a base de impressões digitais de certificados TLS, IDs de commits do Git, cabeçalhos de blocos do Bitcoin e verificação de integridade de arquivos. O algoritmo usa uma construção de Merkle-Damgård com 64 rodadas de compressão para produzir sua saída de 256 bits.

Before · text
After · text
deployment-v4.2.1
a1f7c3d8e9b2...27ae41e4649b (64 caracteres hex)

O digest hexadecimal acima é a representação padrão — 64 caracteres hexadecimais, sempre com o mesmo comprimento independentemente de você calcular o hash de um único byte ou de uma imagem de disco completa.

hashlib.sha256() — A abordagem com a biblioteca padrão

O módulo hashlib acompanha toda instalação Python — não é necessário pip install. Chame hashlib.sha256() com um argumento do tipo bytes para criar um objeto de hash, depois recupere o resultado com .hexdigest() (string hexadecimal) ou .digest() (bytes brutos). O nome da função é em minúsculas: sha256, não SHA256.

Python 3.9+ — hash SHA-256 mínimo
import hashlib

# Calcular hash de uma string de bytes diretamente
digest = hashlib.sha256(b"deployment-v4.2.1").hexdigest()
print(digest)
# a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db

O erro mais comum com hashlib.sha256() é passar uma str em vez de bytes. Strings Python são Unicode e funções de hash operam sobre bytes brutos. Você deve chamar .encode("utf-8") antes de calcular o hash. Isso pega quase todo mundo na primeira vez.

Python 3.9+ — hash de uma string
import hashlib

# Strings devem ser codificadas em bytes antes do hash
config_key = "redis://cache.internal:6379/0"
digest = hashlib.sha256(config_key.encode("utf-8")).hexdigest()
print(digest)
# 7d3f8c2a1b9e4f5d6c8a7b3e2f1d9c4a5b8e7f6d3c2a1b9e4f5d6c8a7b3e2f1d

O método .update() permite alimentar dados de forma incremental. Chamar h.update(a); h.update(b) é equivalente a hashlib.sha256(a + b). É assim que você calcula o hash de arquivos em partes sem carregar o conteúdo inteiro na memória.

Python 3.9+ — hash incremental com update()
import hashlib

h = hashlib.sha256()
h.update(b"request_id=req_7f3a91bc")
h.update(b"&timestamp=1741614120")
h.update(b"&amount=4999")
print(h.hexdigest())
# Equivalente a hashlib.sha256(b"request_id=req_7f3a91bc&timestamp=1741614120&amount=4999").hexdigest()
Nota:.digest() retorna 32 bytes brutos. .hexdigest() retorna uma string hexadecimal de 64 caracteres. Use .digest() ao alimentar o resultado em HMAC, codificação Base64 ou protocolos binários. Use .hexdigest() para logs, colunas de banco de dados e comparação de checksums.

HMAC-SHA256 — Hash com chave usando o módulo hmac

SHA-256 sozinho não tem o conceito de chave secreta — qualquer pessoa com a mesma entrada pode calcular o mesmo hash. Se você precisa provar que uma mensagem veio de um remetente específico (verificação de webhook, assinatura de requisição de API, autenticação de token), você precisa do HMAC. O módulo hmac faz parte da biblioteca padrão do Python e incorpora a chave no processo de hashing, de modo que somente quem possui a chave pode produzir ou verificar o mesmo digest.

Python 3.9+ — HMAC-SHA256 básico
import hmac
import hashlib

# Verificação de assinatura de webhook
secret_key = b"whsec_9f3a7b2e1d4c8a5b"
payload = b'{"event":"invoice.paid","invoice_id":"inv_8d2c","amount":14900}'

signature = hmac.new(secret_key, payload, hashlib.sha256).hexdigest()
print(signature)
# digest HMAC-SHA256 hexadecimal de 64 caracteres

Para verificar um HMAC recebido, use hmac.compare_digest() em vez do operador ==. O operador de igualdade é vulnerável a ataques de temporização — ele interrompe a comparação no primeiro byte diferente, e um atacante pode medir os tempos de resposta para adivinhar a assinatura correta byte a byte. compare_digest() executa em tempo constante independentemente de onde ocorre a divergência.

Python 3.9+ — verificar assinatura de webhook
import hmac
import hashlib

def verify_webhook(payload: bytes, received_sig: str, secret: bytes) -> bool:
    """Verificar assinatura de webhook com comparação em tempo constante."""
    expected = hmac.new(secret, payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, received_sig)

# Simulando verificação de webhook no estilo Stripe
incoming_payload = b'{"event":"payment.completed","amount":4999}'
incoming_signature = "a1b2c3d4e5f6..."  # do cabeçalho X-Signature
webhook_secret = b"whsec_9f3a7b2e1d4c"

if verify_webhook(incoming_payload, incoming_signature, webhook_secret):
    print("Assinatura válida — processar o evento")
else:
    print("Assinatura inválida — rejeitar a requisição")

Assinatura de requisição com HMAC-SHA256

A assinatura de requisições de API segue o mesmo princípio: construa uma string canônica a partir dos componentes da requisição (método, caminho, timestamp, hash do corpo) e assine-a com sua chave secreta. AWS Signature V4, Stripe e webhooks do GitHub usam variações desse padrão.

Python 3.9+ — assinar uma requisição de API com HMAC-SHA256
import hmac
import hashlib
import time

def sign_request(method: str, path: str, body: bytes, secret: bytes) -> str:
    """Criar assinatura HMAC-SHA256 para uma requisição de API."""
    timestamp = str(int(time.time()))
    body_hash = hashlib.sha256(body).hexdigest()

    # String canônica: método + caminho + timestamp + hash do corpo
    canonical = f"{method}\n{path}\n{timestamp}\n{body_hash}"
    signature = hmac.new(secret, canonical.encode("utf-8"), hashlib.sha256).hexdigest()

    return f"ts={timestamp},sig={signature}"

# Uso
api_secret = b"sk_live_9f3a7b2e1d4c8a5b6e7f"
request_body = b'{"customer_id":"cust_4f2a","plan":"enterprise"}'
auth_header = sign_request("POST", "/api/v2/subscriptions", request_body, api_secret)
print(f"Authorization: HMAC-SHA256 {auth_header}")
# Authorization: HMAC-SHA256 ts=1741614120,sig=7d3f8c2a...

HMAC-SHA256 codificado em Base64

Algumas APIs (AWS Signature V4, gateways de pagamento) esperam o resultado do HMAC como uma string codificada em Base64 em vez de hexadecimal. A diferença: hex usa 64 caracteres, Base64 usa 44 caracteres para o mesmo digest de 32 bytes.

Python 3.9+ — HMAC-SHA256 codificado em Base64
import hmac
import hashlib
import base64

secret = b"webhook_secret_9f3a"
message = b"POST /api/v2/events 1741614120"

# Saída hex: 64 caracteres
hex_sig = hmac.new(secret, message, hashlib.sha256).hexdigest()
print(f"Hex:    {hex_sig}")

# Saída Base64: 44 caracteres (mais curta, comum em cabeçalhos HTTP)
raw_sig = hmac.new(secret, message, hashlib.sha256).digest()
b64_sig = base64.b64encode(raw_sig).decode("ascii")
print(f"Base64: {b64_sig}")

Hash de datetime, UUID e objetos customizados

SHA-256 opera sobre bytes brutos, portanto tipos não-bytes — datetime, UUID, dataclasses, modelos Pydantic — devem ser serializados em bytes antes do hash. Não há conversão automática; você escolhe a representação canônica. Para hashing determinístico entre sistemas, sempre use uma codificação explícita e um formato de serialização estável (ISO 8601 para datetimes, a forma de string padrão para UUIDs, JSON com chaves ordenadas para dicts).

Python 3.9+ — hash de datetime e UUID
import hashlib
import uuid
from datetime import datetime, timezone

# datetime — use ISO 8601 com offset UTC explícito para portabilidade
event_time = datetime(2026, 3, 28, 12, 0, 0, tzinfo=timezone.utc)
time_hash = hashlib.sha256(event_time.isoformat().encode("utf-8")).hexdigest()
print(f"hash do datetime: {time_hash[:16]}...")

# UUID — calcular hash da forma de string canônica (minúsculas, com hífens)
record_id = uuid.uuid4()
uuid_hash = hashlib.sha256(str(record_id).encode("utf-8")).hexdigest()
print(f"hash do UUID: {uuid_hash[:16]}...")

Para objetos customizados, serialize para uma representação bytes canônica antes do hash. JSON com chaves ordenadas funciona bem para objetos semelhantes a dicts:

Python 3.9+ — hash de objeto customizado
import hashlib
import json
from dataclasses import dataclass, asdict

@dataclass
class Evento:
    id: str
    tipo: str
    valor: int
    timestamp: str

def hash_evento(evento: Evento) -> str:
    """Calcular hash de uma instância de dataclass usando JSON com chaves ordenadas para determinismo."""
    canonical = json.dumps(asdict(evento), sort_keys=True, separators=(",", ":"))
    return hashlib.sha256(canonical.encode("utf-8")).hexdigest()

e = Evento(id="evt_4f2a", tipo="pagamento.concluido", valor=4999, timestamp="2026-03-28T12:00:00Z")
print(hash_evento(e))  # estável entre execuções e máquinas
Nota:Sempre ordene as chaves do dict (sort_keys=True) ao calcular o hash de objetos serializados em JSON. A ordem de inserção de dicts é preservada no Python 3.7+, mas pode diferir entre caminhos de serialização, produzindo hashes diferentes para dados idênticos.

Checksum SHA-256 de arquivo — verificar downloads e artefatos

Calcular o checksum SHA-256 de um arquivo é um dos usos mais comuns do algoritmo. Você o encontra em todo lugar: páginas de release de binários Go, arquivos wheel Python, manifestos de imagem Docker, atualizações de firmware. A chave é ler o arquivo em partes em vez de carregá-lo todo de uma vez — uma imagem ISO de 2 GB não deve exigir 2 GB de RAM só para calculá-la.

Python 3.9+ — checksum SHA-256 de um arquivo (em partes)
import hashlib

def sha256_checksum(filepath: str, chunk_size: int = 8192) -> str:
    """Calcular hash SHA-256 de um arquivo, lendo em partes para economizar memória."""
    h = hashlib.sha256()
    with open(filepath, "rb") as f:
        for chunk in iter(lambda: f.read(chunk_size), b""):
            h.update(chunk)
    return h.hexdigest()

# Hash de um artefato de release
checksum = sha256_checksum("/tmp/release-v4.2.1.tar.gz")
print(f"SHA-256: {checksum}")

O Python 3.11 adicionou hashlib.file_digest(), que faz a leitura em partes internamente e pode usar otimizações de cópia zero em plataformas compatíveis. Se você está no 3.11 ou posterior, prefira-o ao loop manual.

Python 3.11+ — hashlib.file_digest()
import hashlib

with open("/tmp/release-v4.2.1.tar.gz", "rb") as f:
    digest = hashlib.file_digest(f, "sha256")

print(digest.hexdigest())

Verificar um arquivo baixado contra um checksum conhecido

Python 3.9+ — verificação de checksum
import hashlib
import hmac as hmac_mod  # apenas para compare_digest

def verify_checksum(filepath: str, expected_hex: str) -> bool:
    """Verificar checksum SHA-256 com comparação em tempo constante."""
    h = hashlib.sha256()
    with open(filepath, "rb") as f:
        for chunk in iter(lambda: f.read(8192), b""):
            h.update(chunk)
    return hmac_mod.compare_digest(h.hexdigest(), expected_hex.lower())

# Verificar um artefato de release
expected = "a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db"
if verify_checksum("/tmp/release-v4.2.1.tar.gz", expected):
    print("Checksum correto — arquivo íntegro")
else:
    print("Checksum inválido — arquivo pode estar corrompido ou adulterado")
Nota:Sempre use hmac.compare_digest() para comparação de checksums, mesmo quando não há chave secreta envolvida. A comparação em tempo constante evita vazamentos de informação baseados em temporização. O operador == funciona corretamente, mas não é seguro para contextos sensíveis à segurança.

SHA-256 com codificação Base64

Alguns protocolos esperam o digest SHA-256 como string Base64 em vez de hexadecimal. Cabeçalhos HTTP como Content-Digest e Integrity (Subresource Integrity em navegadores) usam Base64, e assinaturas JWT são codificadas em Base64url. O ponto chave é codificar em Base64 os bytes brutos do .digest(), não a string hexadecimal.

Python 3.9+ — SHA-256 codificado em Base64
import hashlib
import base64

data = b"integrity check payload"

# Correto: Base64 de bytes brutos (32 bytes → 44 caracteres Base64)
raw_digest = hashlib.sha256(data).digest()
b64_digest = base64.b64encode(raw_digest).decode("ascii")
print(f"sha256-{b64_digest}")
# sha256-<44 caracteres>

# Errado: Base64 da string hexadecimal (64 bytes ASCII → 88 caracteres Base64 — o dobro do tamanho)
hex_digest = hashlib.sha256(data).hexdigest()
wrong = base64.b64encode(hex_digest.encode()).decode()
print(f"Comprimento errado: {len(wrong)} chars")  # 88 — não é o que as APIs esperam
Aviso:Codificar em Base64 a string hexadecimal em vez dos bytes brutos é um erro comum que produz uma saída com o dobro do tamanho esperado. As APIs vão rejeitá-la e a mensagem de erro geralmente não dá nenhuma pista sobre o motivo. Sempre chame .digest(), não .hexdigest(), antes da codificação Base64.

Referência do hashlib.sha256()

O construtor e os métodos de um objeto de hash SHA-256:

Parâmetro / Método
Tipo
Descrição
data (posicional)
bytes
Dados iniciais para calcular o hash — equivale a chamar update(data) logo após a construção
.update(data)
bytes
Alimenta bytes adicionais no estado do hash — pode ser chamado várias vezes para entrada em partes
.digest()
→ bytes
Retorna os 32 bytes brutos do digest — use para entradas de HMAC, protocolos binários e codificação Base64
.hexdigest()
→ str
Retorna a string hexadecimal de 64 caracteres em minúsculas — representação padrão para checksums e verificação
.copy()
→ hash object
Retorna uma cópia do estado atual do hash — permite ramificar um digest sem recalcular do início
hashlib.sha256()
construtor
Cria um novo objeto de hash SHA-256 apoiado pelo OpenSSL no CPython — usedfips=True no 3.9+ restringe a algoritmos aprovados pelo FIPS

Parâmetros de hmac.new() para hash com chave:

Parâmetro
Tipo
Descrição
key
bytes
A chave secreta — deve ser bytes, não str
msg
bytes | None
Mensagem inicial a autenticar — None por padrão, pode-se chamar update() depois
digestmod
str | callable
Algoritmo de hash: passe hashlib.sha256 ou a string "sha256"

A biblioteca cryptography — Uma API alternativa para SHA-256

O pacote cryptography oferece uma API diferente para SHA-256 por meio de suas primitivas hazmat. Raramente a uso quando tudo que preciso é um hash — o hashlib é mais simples e não tem dependência externa. Mas se seu projeto já depende do cryptography para TLS, X.509 ou criptografia simétrica, usar sua API de hash mantém tudo sob uma única biblioteca e oferece tratamento de erros consistente.

Python 3.9+ — SHA-256 com a biblioteca cryptography
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend

digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(b"deployment-v4.2.1")
result = digest.finalize()  # 32 bytes brutos

print(result.hex())  # string hexadecimal de 64 caracteres
# a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db
Aviso:A biblioteca cryptography requer pip install cryptography. O objeto de hash é de uso único: chamar .finalize() uma segunda vez lança AlreadyFinalized. Use .copy() antes de finalizar se precisar ramificar o estado do hash.

Hash de arquivo e de resposta de API

Dois cenários surgem constantemente: calcular o hash de um arquivo em disco para verificar um artefato de release, e calcular o hash do corpo de uma resposta HTTP para usar como chave de cache ou verificar um webhook.

Ler arquivo → Calcular SHA-256 → Comparar

Python 3.9+ — hash de backup de configuração com tratamento de erros
import hashlib
import sys

def hash_file_safe(filepath: str) -> str | None:
    """Calcular hash de um arquivo com tratamento adequado de erros."""
    try:
        h = hashlib.sha256()
        with open(filepath, "rb") as f:
            for chunk in iter(lambda: f.read(16384), b""):
                h.update(chunk)
        return h.hexdigest()
    except FileNotFoundError:
        print(f"Erro: {filepath} não encontrado", file=sys.stderr)
        return None
    except PermissionError:
        print(f"Erro: sem permissão de leitura para {filepath}", file=sys.stderr)
        return None

result = hash_file_safe("/etc/nginx/nginx.conf")
if result:
    print(f"SHA-256: {result}")

Resposta HTTP → Hash do corpo como chave de cache

Python 3.9+ — hash de resposta de API
import hashlib
import urllib.request
import json

def fetch_and_hash(url: str) -> tuple[dict, str]:
    """Buscar JSON de uma API e retornar tanto os dados quanto seu hash SHA-256."""
    try:
        with urllib.request.urlopen(url, timeout=10) as resp:
            body = resp.read()
            content_hash = hashlib.sha256(body).hexdigest()
            data = json.loads(body)
            return data, content_hash
    except urllib.error.URLError as exc:
        raise ConnectionError(f"Falha ao buscar {url}: {exc}") from exc

# Chave de cache baseada no conteúdo da resposta
data, digest = fetch_and_hash("https://api.exchange.internal/v2/rates")
print(f"Hash da resposta: {digest[:16]}...")
print(f"EUR/BRL: {data.get('rates', {}).get('EUR', 'N/A')}")

Para uma verificação rápida sem código, o gerador SHA-256 do ToolDeck roda inteiramente no seu navegador.

Hash SHA-256 na linha de comando

Às vezes você precisa de um hash rápido no terminal durante um incidente ou deploy. O módulo hashlib do Python não tem subcomando de CLI embutido (ao contrário do python3 -m json.tool), mas você pode usar um one-liner ou ferramentas do sistema.

bash — hash de string na linha de comando
# One-liner Python
echo -n "deployment-v4.2.1" | python3 -c "import hashlib,sys; print(hashlib.sha256(sys.stdin.buffer.read()).hexdigest())"

# macOS / BSD
echo -n "deployment-v4.2.1" | shasum -a 256

# Linux (coreutils)
echo -n "deployment-v4.2.1" | sha256sum

# OpenSSL (multiplataforma)
echo -n "deployment-v4.2.1" | openssl dgst -sha256
bash — hash de arquivo
# Hash de um tarball de release
sha256sum release-v4.2.1.tar.gz
# ou
openssl dgst -sha256 release-v4.2.1.tar.gz

# Verificar contra um checksum conhecido
echo "a8f5f167f44f4964e6c998dee827110c release-v4.2.1.tar.gz" | sha256sum -c -
# release-v4.2.1.tar.gz: OK
Nota:Sempre use echo -n (sem nova linha no final) ao calcular hash de strings na linha de comando. Um echo simples acrescenta \n, o que altera o hash. Esta é a principal razão pela qual as pessoas obtêm hashes diferentes entre Python e o shell.

Alternativa de alta performance — hashlib com OpenSSL e pycryptodome

No CPython, hashlib.sha256() já delega para a implementação C do OpenSSL, portanto é rápido — tipicamente 500+ MB/s em hardware moderno.

Se o hashing SHA-256 aparecer no seu profiler — por exemplo, ao calcular checksums de milhares de arquivos num pipeline de CI ou ao calcular o hash de cada corpo de requisição num gateway de API de alta demanda — existem duas opções: otimizar o padrão de chamada do hashlib, ou mudar para pycryptodome para uma API de criptografia unificada que também cobre SHA-3 e BLAKE2:

bash — instalar pycryptodome
pip install pycryptodome
Python 3.9+ — SHA-256 com pycryptodome
from Crypto.Hash import SHA256

h = SHA256.new()
h.update(b"deployment-v4.2.1")
print(h.hexdigest())
# a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db

Para hashing paralelo de arquivos em alta demanda, os maiores ganhos vêm da redução do overhead do Python por meio de partes maiores e threads:

Python 3.9+ — hash em lote de arquivos com hashlib
import hashlib
import os
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor

def hash_file(path: Path) -> tuple[str, str]:
    """Calcular hash de um único arquivo e retornar (caminho, digest hex)."""
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(65536), b""):  # partes de 64 KB
            h.update(chunk)
    return str(path), h.hexdigest()

def hash_directory(directory: str, pattern: str = "*.tar.gz") -> dict[str, str]:
    """Calcular hash de todos os arquivos correspondentes em paralelo usando threads."""
    files = list(Path(directory).glob(pattern))
    results = {}
    with ThreadPoolExecutor(max_workers=os.cpu_count()) as pool:
        for path, digest in pool.map(hash_file, files):
            results[path] = digest
    return results

# Calcular hash de todos os artefatos de release em paralelo
checksums = hash_directory("/var/releases", "*.tar.gz")
for path, digest in checksums.items():
    print(f"{digest}  {path}")

Usar partes de 64 KB em vez de 8 KB reduz em 8x o número de chamadas Python para C. Threads funcionam bem aqui porque o GIL é liberado durante o hashing em nível C — o gargalo é a E/S de disco, não a CPU.

Saída no terminal com destaque de sintaxe

A biblioteca rich é útil quando você precisa verificar um lote de arquivos e quer uma tabela mostrando o status aprovado/reprovado por arquivo em vez de saída hexadecimal rolando pela tela.

bash — instalar rich
pip install rich
Python 3.9+ — saída rich para verificação de hash
import hashlib
from pathlib import Path
from rich.console import Console
from rich.table import Table

console = Console()

def hash_and_display(files: list[str], expected: dict[str, str]) -> None:
    """Calcular hash dos arquivos e exibir resultados com verificação colorida."""
    table = Table(title="Verificação SHA-256")
    table.add_column("Arquivo", style="cyan")
    table.add_column("SHA-256", style="dim", max_width=20)
    table.add_column("Status")

    for filepath in files:
        h = hashlib.sha256()
        with open(filepath, "rb") as f:
            for chunk in iter(lambda: f.read(8192), b""):
                h.update(chunk)
        digest = h.hexdigest()

        name = Path(filepath).name
        status = "[green]✓ OK[/green]" if expected.get(name) == digest else "[red]✗ DIVERGÊNCIA[/red]"
        table.add_row(name, f"{digest[:16]}...", status)

    console.print(table)

# Uso
expected_checksums = {
    "api-gateway-v3.1.tar.gz": "a8f5f167f44f4964...",
    "worker-v3.1.tar.gz": "7d3f8c2a1b9e4f5d...",
}
hash_and_display(
    ["/var/releases/api-gateway-v3.1.tar.gz", "/var/releases/worker-v3.1.tar.gz"],
    expected_checksums,
)
Nota:A saída do rich é apenas para exibição no terminal. Não escreva códigos de escape ANSI em arquivos de log ou respostas de API — remova-os com console.print(data, highlight=False) ou redirecione para um arquivo com Console(file=open(...)).

Trabalhando com arquivos grandes

O padrão de .update() em partes lida com arquivos de qualquer tamanho com uso constante de memória. Para arquivos muito grandes (imagens de disco de vários GB, backups de banco de dados), a preocupação principal muda de memória para feedback ao usuário — calcular o hash de 10 GB a 500 MB/s ainda leva 20 segundos, e o silêncio durante esse tempo deixa as pessoas preocupadas.

Python 3.9+ — hash de arquivos grandes com relatório de progresso
import hashlib
import os

def sha256_with_progress(filepath: str) -> str:
    """Calcular hash de um arquivo grande com relatório de progresso na stderr."""
    file_size = os.path.getsize(filepath)
    h = hashlib.sha256()
    bytes_read = 0

    with open(filepath, "rb") as f:
        while chunk := f.read(1 << 20):  # partes de 1 MB
            h.update(chunk)
            bytes_read += len(chunk)
            pct = (bytes_read / file_size) * 100
            print(f"\r  Calculando hash: {pct:.1f}% ({bytes_read >> 20} MB / {file_size >> 20} MB)",
                  end="", flush=True)

    print()  # nova linha após o progresso
    return h.hexdigest()

digest = sha256_with_progress("/mnt/backups/db-snapshot-2026-03.sql.gz")
print(f"SHA-256: {digest}")

NDJSON / JSON Lines — Hash de cada registro separadamente

Python 3.9+ — hash de registros individuais em um stream NDJSON
import hashlib
import json

def hash_ndjson_records(filepath: str) -> dict[str, str]:
    """Calcular hash de cada registro JSON em um arquivo NDJSON para deduplicação."""
    seen = {}
    with open(filepath, "r", encoding="utf-8") as f:
        for line_num, line in enumerate(f, 1):
            line = line.strip()
            if not line:
                continue
            try:
                record = json.loads(line)
                # Normalizar antes do hash: ordenar chaves para saída determinística
                canonical = json.dumps(record, sort_keys=True, separators=(",", ":"))
                digest = hashlib.sha256(canonical.encode("utf-8")).hexdigest()

                if digest in seen:
                    print(f"Linha {line_num}: duplicata da linha {seen[digest]}")
                else:
                    seen[digest] = line_num
            except json.JSONDecodeError:
                print(f"Linha {line_num}: JSON inválido, ignorado")

    print(f"Processadas {line_num} linhas, {len(seen)} registros únicos")
    return seen

hash_ndjson_records("telemetry-events-2026-03.ndjson")
Nota:Mude do one-shot hashlib.sha256(data) para o loop de.update() em partes quando os arquivos ultrapassarem 50–100 MB. Abaixo desse limite, ler o arquivo inteiro com f.read() é suficiente — o uso de memória será aproximadamente igual ao tamanho do arquivo.

Erros comuns

Passar str em vez de bytes para hashlib.sha256()

Problema: hashlib.sha256('texto') lança TypeError: Unicode-objects must be encoded before hashing. A função requer bytes, não str.

Solução: Codifique a string primeiro: hashlib.sha256('texto'.encode('utf-8')). Ou use um literal b'' para valores fixos no código.

Before · Python
After · Python
import hashlib
digest = hashlib.sha256("deployment-v4.2.1").hexdigest()
# TypeError: Unicode-objects must be encoded before hashing
import hashlib
digest = hashlib.sha256("deployment-v4.2.1".encode("utf-8")).hexdigest()
# Correto — retorna string hexadecimal de 64 caracteres
Usar == em vez de hmac.compare_digest() para verificação de assinatura

Problema: O operador == interrompe a comparação no primeiro byte diferente. Um atacante pode medir o tempo de resposta para adivinhar a assinatura correta byte a byte.

Solução: Use hmac.compare_digest() para todas as comparações sensíveis à segurança — ele executa em tempo constante independentemente de onde ocorre a divergência.

Before · Python
After · Python
received_sig = request.headers["X-Signature"]
expected_sig = hmac.new(key, body, hashlib.sha256).hexdigest()
if received_sig == expected_sig:  # vulnerável a ataque de temporização
    process_webhook(body)
received_sig = request.headers["X-Signature"]
expected_sig = hmac.new(key, body, hashlib.sha256).hexdigest()
if hmac.compare_digest(received_sig, expected_sig):  # tempo constante
    process_webhook(body)
Codificar em Base64 a string hexadecimal em vez dos bytes brutos

Problema: base64.b64encode(digest.hexdigest().encode()) produz uma string de 88 caracteres — o dobro dos 44 esperados. APIs que esperam SHA-256 codificado em Base64 vão rejeitá-la.

Solução: Chame .digest() (bytes brutos) antes da codificação Base64, não .hexdigest() (string hexadecimal).

Before · Python
After · Python
import hashlib, base64
hex_str = hashlib.sha256(data).hexdigest()
b64 = base64.b64encode(hex_str.encode())  # 88 chars — errado!
import hashlib, base64
raw = hashlib.sha256(data).digest()
b64 = base64.b64encode(raw)  # 44 chars — correto
Carregar um arquivo grande inteiro na memória antes do hash

Problema: hashlib.sha256(open('large.iso', 'rb').read()) carrega o arquivo inteiro na memória. Um arquivo de 4 GB requer 4 GB de RAM só para a computação do hash.

Solução: Leia em partes com um loop e .update(). O uso de memória permanece constante independentemente do tamanho do arquivo.

Before · Python
After · Python
import hashlib
# Carrega 4 GB inteiros na memória
digest = hashlib.sha256(open("disk.iso", "rb").read()).hexdigest()
import hashlib
h = hashlib.sha256()
with open("disk.iso", "rb") as f:
    for chunk in iter(lambda: f.read(8192), b""):
        h.update(chunk)
digest = h.hexdigest()  # uso de memória constante

hashlib vs hmac vs alternativas — Comparação rápida

Método
Saída
Com chave
Velocidade
Streaming de arquivo
Requer instalação
Tipos customizados
hashlib.sha256()
hex / bytes
Rápido (C/OpenSSL)
✓ via update()
Não (stdlib)
encode() manual
hmac.new()
hex / bytes
Rápido (C/OpenSSL)
✓ via update()
Não (stdlib)
encode() manual
hashlib.file_digest()
hex / bytes
Rápido (zero-copy)
✓ (embutido)
Não (3.11+)
encode() manual
cryptography hashes.SHA256()
bytes
Rápido (OpenSSL)
✓ via update()
pip install
encode() manual
subprocess openssl dgst
string hex
✗ / ✓
Mais lento (fork)
✓ (nível do SO)
openssl do sistema
encode() manual
pyhashcat / custom
variado
Acelerado por GPU
pip install
encode() manual

Para hashing direto — checksums, chaves de cache, fingerprinting de conteúdo — use hashlib.sha256(). Mude para hmac.new() assim que precisar de uma chave secreta (webhooks, assinaturas de API, autenticação de token). Recorra à biblioteca cryptography somente se seu projeto já a utiliza para criptografia ou TLS — adicionar uma dependência de extensão C apenas para hashing é excessivo quando o hashlib já usa o OpenSSL por baixo.

É possível descriptografar SHA-256? — Hashing vs criptografia

Resposta curta: não. SHA-256 é uma função unidirecional. O algoritmo é projetado para ser irreversível — você não pode reconstruir a entrada original a partir do digest de 256 bits. Esta não é uma limitação de implementação; é uma propriedade matemática da função de hash. O espaço de saída de 256 bits é astronomicamente grande (2256 valores possíveis), e a função descarta informação durante suas 64 rodadas de compressão.

Atacantes podem tentar força bruta ou ataques de dicionário contra entradas fracas (senhas comuns, strings curtas), mas para qualquer entrada com entropia razoável — chaves de API, tokens aleatórios, conteúdo de arquivo — reverter o SHA-256 é computacionalmente inviável com o hardware atual. Se você precisar de transformação reversível, use criptografia simétrica:

Python 3.9+ — criptografia vs hashing
# Hashing — unidirecional, não é possível recuperar o original
import hashlib
digest = hashlib.sha256(b"secret-config-value").hexdigest()
# Não há como obter "secret-config-value" de volta a partir do digest

# Criptografia — bidirecional, pode descriptografar com a chave
from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher = Fernet(key)
encrypted = cipher.encrypt(b"secret-config-value")
decrypted = cipher.decrypt(encrypted)
print(decrypted)  # b"secret-config-value" — original recuperado

Para gerar um hash SHA-256 rapidamente sem instalar nada, a ferramenta online roda inteiramente no seu navegador.

Como verificar se uma string é um hash SHA-256 válido em Python

Um digest SHA-256 hexadecimal válido tem exatamente 64 caracteres hexadecimais (0-9, a-f, A-F). Uma validação rápida antes de processar entradas não confiáveis evita erros confusos mais adiante.

Python 3.9+ — validar formato SHA-256
import re

def is_sha256_hex(value: str) -> bool:
    """Verificar se uma string corresponde ao formato de digest SHA-256 hexadecimal."""
    return bool(re.fullmatch(r"[a-fA-F0-9]{64}", value))

# Casos de teste
print(is_sha256_hex("e3b0c44298fc1c149afbf4c8996fb924"
                     "27ae41e4649b934ca495991b7852b855"))  # True — SHA-256 da string vazia
print(is_sha256_hex("e3b0c44298fc1c14"))                   # False — muito curto
print(is_sha256_hex("zzzz" * 16))                          # False — caracteres hex inválidos
Nota:Isso valida apenas o formato, não se o hash foi calculado a partir de alguma entrada específica. Não há como distinguir se uma string hexadecimal de 64 caracteres é um digest SHA-256 "real" ou apenas dados hexadecimais aleatórios — a saída do SHA-256 é indistinguível de dados aleatórios por design.

Perguntas frequentes

Como calcular o hash de uma string com SHA-256 em Python?

Chame hashlib.sha256() com a string codificada em bytes. Strings em Python são Unicode e funções de hash operam sobre bytes brutos, portanto você deve chamar .encode("utf-8") primeiro. O método .hexdigest() retorna a conhecida string hexadecimal de 64 caracteres.

Python
import hashlib

api_key = "sk_live_9f3a7b2e1d4c"
digest = hashlib.sha256(api_key.encode("utf-8")).hexdigest()
print(digest)
# e3b7c4a1f8d2...64 caracteres hexadecimais

É possível descriptografar um hash SHA-256 e recuperar o texto original?

Não. SHA-256 é uma função unidirecional — ela mapeia uma entrada de comprimento arbitrário para uma saída fixa de 256 bits e descarta a estrutura durante o processo. Não existe inversa matemática. Atacantes podem tentar força bruta ou tabelas rainbow contra entradas fracas (senhas curtas, palavras comuns), mas para qualquer entrada com entropia razoável, reverter o SHA-256 é computacionalmente inviável. Se você precisar de transformação reversível, use criptografia (AES-GCM, Fernet) em vez de hash.

Qual a diferença entre .digest() e .hexdigest()?

.digest() retorna os 32 bytes brutos do hash como um objeto bytes. .hexdigest() retorna os mesmos dados codificados como uma string hexadecimal de 64 caracteres em minúsculas. Use .digest() quando precisar de saída binária — para alimentar HMAC, codificação Base64 ou protocolos binários. Use .hexdigest() quando precisar de uma string legível para logs, armazenamento em banco de dados ou comparação de checksums.

Python
import hashlib

h = hashlib.sha256(b"deployment-v4.2.1")
print(len(h.digest()))     # 32 (bytes)
print(len(h.hexdigest()))  # 64 (caracteres hexadecimais)

Como calcular o checksum SHA-256 de um arquivo em Python?

Abra o arquivo em modo binário e alimente-o ao hasher em partes com .update(). No Python 3.11+, use hashlib.file_digest() para uma API ainda mais simples. Nunca chame f.read() em arquivos grandes — isso carrega o arquivo inteiro na memória.

Python
import hashlib

def sha256_file(path: str) -> str:
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(8192), b""):
            h.update(chunk)
    return h.hexdigest()

print(sha256_file("release-v4.2.1.tar.gz"))

Como criar uma assinatura HMAC-SHA256 em Python?

Use o módulo hmac com hashlib.sha256 como digestmod. Passe a chave secreta e a mensagem como bytes. O resultado é um hash com chave que prova tanto a integridade quanto a autenticidade — o receptor precisa da mesma chave para verificar.

Python
import hmac
import hashlib

secret = b"webhook_secret_9f3a"
payload = b'{"event":"payment.completed","amount":4999}'
signature = hmac.new(secret, payload, hashlib.sha256).hexdigest()
print(signature)  # HMAC hexadecimal de 64 caracteres

Como verificar se uma string é um digest SHA-256 hexadecimal válido?

Um digest SHA-256 hexadecimal tem exatamente 64 caracteres hexadecimais. Use uma expressão regular ou uma verificação simples de comprimento mais caracteres. A abordagem com regex é a mais legível.

Python
import re

def is_sha256(s: str) -> bool:
    return bool(re.fullmatch(r"[a-fA-F0-9]{64}", s))

print(is_sha256("e3b0c44298fc1c149afbf4c8996fb924"
                 "27ae41e4649b934ca495991b7852b855"))  # True
print(is_sha256("not-a-hash"))  # False

Ferramentas relacionadas

DV
Dmitri VolkovDevOps Engineer & Python Automation Specialist

Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.

MS
Maria SantosRevisor técnico

Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.