MD5 vs SHA-1 vs SHA-256: qual hash usar?

Use SHA-256 em tudo o que envolve segurança; MD5 e SHA-1 só são aceitáveis quando ninguém ganha nada forjando um hash igual.

MD5, SHA-1 e SHA-256 fazem o mesmo trabalho: transformam uma entrada de qualquer tamanho em uma impressão digital curta e de tamanho fixo, chamada de resumo (em inglês, digest). A mesma entrada sempre gera o mesmo resumo, e mudar um único bit muda o resultado inteiro. Os três diferem no tamanho do resumo, na velocidade e, principalmente, em uma questão: alguém consegue produzir de propósito duas entradas diferentes com o mesmo resumo? Com MD5 e SHA-1 isso já foi feito publicamente. Com SHA-256, não.

Os três algoritmos lado a lado

MD5SHA-1SHA-256
Tamanho do resumo128 bits, 32 caracteres hexadecimais160 bits, 40 caracteres hexadecimais256 bits, 64 caracteres hexadecimais
Publicação1992 (RFC 1321)1995 (FIPS 180-1)2001, como parte da família SHA-2
ColisõesPráticas desde 2004Práticas desde 2017Nenhum ataque conhecido
Encontrar uma entrada para um resumo dadoNenhum ataque práticoNenhum ataque práticoNenhum ataque prático
Serve hoje paraChecksums sem fins de segurança, chaves de cacheSó compatibilidade com sistemas legadosO padrão para qualquer projeto novo

Estes são os resumos completos dos cinco bytes hello, como impressos por md5sum, sha1sum e sha256sum. O Gerador de Hash mostra os mesmos valores lado a lado, além de SHA-384 e SHA-512, para um texto ou para um arquivo de até 50 MB.

MD5      5d41402abc4b2a76b9719d911017c592
SHA-1    aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
SHA-256  2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

O que os bits a mais compram

O tamanho do resumo define o custo de um ataque genérico, aquele que trata a função como uma caixa-preta. Por causa do paradoxo do aniversário, encontrar quaisquer duas entradas que colidem exige cerca de 2^(n/2) tentativas para um resumo de n bits: 2^64 para o MD5, 2^80 para o SHA-1 e 2^128 para o SHA-256. Encontrar uma entrada que corresponda a um resumo específico (uma pré-imagem) exige cerca de 2^n.

Esses números só valem enquanto o projeto do algoritmo não tem atalhos. MD5 e SHA-1 têm atalhos para gerar colisões, e é por isso que o tamanho deles já não conta a história toda. O SHA-256 não tem nenhum atalho conhecido, e 2^128 está muito além de todo o poder computacional que existe.

Como o MD5 e o SHA-1 foram quebrados

Um ataque de colisão não permite que ninguém reverta um hash. Ele permite que o atacante prepare de antemão duas entradas diferentes com o mesmo resumo, faça uma delas ser aceita como confiável e depois a troque pela outra. A variante perigosa é a colisão de prefixo escolhido (chosen-prefix): o atacante escolhe dois inícios com significado, como dois certificados com nomes diferentes, e calcula bytes extras que tornam os resumos iguais.

  • MD5, 2004: Xiaoyun Wang e colegas publicaram colisões práticas de MD5.
  • MD5, 2008: uma equipe de pesquisadores usou uma colisão MD5 de prefixo escolhido para criar um certificado falso de autoridade certificadora em que os navegadores teriam confiado, porque uma CA comercial ainda assinava certificados com MD5.
  • MD5, 2012: o malware Flame usou uma colisão MD5 para forjar um certificado de assinatura de código da Microsoft.
  • SHA-1, 2017: o Google e o CWI Amsterdam anunciaram o SHAttered, dois arquivos PDF diferentes com o mesmo resumo SHA-1. A equipe relatou cerca de 6.500 anos de CPU e 110 anos de GPU de processamento.
  • SHA-1, 2020: Gaëtan Leurent e Thomas Peyrin publicaram uma colisão SHA-1 prática de prefixo escolhido e a usaram para se passar por uma chave PGP.

Os navegadores deixaram de aceitar certificados TLS com SHA-1 em 2017, e o NIST anunciou em dezembro de 2022 que o SHA-1 deve ser abandonado por completo até o fim de 2030. Nem o MD5 nem o SHA-1 têm um ataque prático de pré-imagem: tendo apenas o resumo, ninguém consegue encontrar uma entrada que o produza. É por isso que os dois ainda funcionam para detectar danos acidentais.

Velocidade: medida, não suposta

O MD5 costuma ser descrito como o mais rápido. Calculamos o hash dos mesmos 256 MB de dados aleatórios com o Node 24 (OpenSSL 3.5) em um computador de mesa, três execuções para cada algoritmo:

AlgoritmoVazão nessa máquina
SHA-1cerca de 1.000 MB/s
MD5cerca de 730 MB/s
SHA-512cerca de 690 MB/s
SHA-256cerca de 460 MB/s

A ordem depende do processador. Essa CPU não tem as extensões do conjunto de instruções SHA; processadores que as têm aceleram o SHA-1 e o SHA-256 em hardware, e aí o SHA-256 pode passar o MD5. O SHA-512 venceu o SHA-256 aqui porque trabalha com palavras de 64 bits. Com entradas curtas a diferença some: um milhão de hashes de um endereço de e-mail curto levou entre 1,8 e 2,1 segundos com cada um dos três, MD5, SHA-1 e SHA-256, porque o custo de cada chamada pesa mais do que o próprio cálculo do hash. Velocidade quase nunca é um motivo real para escolher o MD5.

Onde cada um ainda serve

  • MD5: detectar corrupção acidental, eliminar duplicatas entre os seus próprios arquivos, chaves de cache e ETags, e conversar com sistemas legados que esperam esse formato. Nunca para assinaturas, certificados ou verificações de integridade em que um atacante possa fornecer o arquivo.
  • SHA-1: sistemas existentes que você ainda não pode mudar. O Git nomeia objetos com SHA-1 há muito tempo, usando uma implementação reforçada que detecta os ataques de colisão conhecidos, e também aceita repositórios que usam SHA-256. O HMAC-SHA1, algoritmo padrão por trás dos códigos TOTP dos apps autenticadores, não é afetado por ataques de colisão.
  • SHA-256: checksums de downloads, assinaturas digitais, certificados, HMAC, endereçamento por conteúdo e qualquer coisa nova. Use o SHA-256 quando um checksum precisa resistir a adulteração, e deixe o MD5 para os valores legados que você ainda precisa conferir.

Vai conferir um download? O Verificador de Checksum de Arquivos calcula o hash do arquivo localmente e informa com qual algoritmo um checksum colado corresponde.

Nenhum deles serve para guardar senhas

Os três foram projetados para ser rápidos, e rapidez é exatamente o que quer um atacante que testa bilhões de senhas. Um salt impede o uso de tabelas pré-calculadas, mas não deixa as tentativas mais lentas. Armazenar senhas exige uma função deliberadamente lenta e, de preferência, que consuma muita memória (memory-hard). Na mesma máquina do teste acima:

Função e parâmetrosTempo por senha
SHA-256, uma chamada no Nodecerca de 2,5 microssegundos
Argon2id, 19 MiB de memória, 2 iterações, 1 via (lane)cerca de 33 milissegundos
PBKDF2-HMAC-SHA256, 600.000 iteraçõescerca de 270 milissegundos
scrypt, N=2^17, r=8, p=1cerca de 310 milissegundos

Esses parâmetros são os mínimos do OWASP Password Storage Cheat Sheet, que recomenda primeiro o Argon2id, depois o scrypt, o bcrypt com fator de trabalho 10 ou maior para sistemas legados e o PBKDF2 quando a conformidade com FIPS-140 é obrigatória. Use a API de hash de senhas do seu framework em vez de montar uma solução a partir de um hash comum.

HMAC: quando o hash precisa de uma chave

Para provar que uma mensagem veio de alguém que conhece um segredo, não calcule sha256(secret + message). MD5, SHA-1 e SHA-256 são todos vulneráveis a extensão de comprimento (length extension): conhecer o resumo de uma mensagem permite ao atacante calcular um resumo válido para essa mensagem com dados extras no final, sem saber o segredo. O HMAC (RFC 2104) evita isso. O HMAC-SHA256 é a escolha padrão, e todos os trechos abaixo imprimem o mesmo valor:

// Node.js
crypto.createHmac('sha256', 'secret').update('hello').digest('hex')

# Python
hmac.new(b'secret', b'hello', hashlib.sha256).hexdigest()

// PHP
hash_hmac('sha256', 'hello', 'secret')

// 88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b

Compare HMACs com uma função de tempo constante, como crypto.timingSafeEqual, hmac.compare_digest ou hash_equals, e não com ==.

Calcular hashes no terminal e no código

# Linux (coreutils)
md5sum file.iso
sha1sum file.iso
sha256sum file.iso

# macOS
md5 file.iso
shasum -a 1 file.iso
shasum -a 256 file.iso

# Windows PowerShell
Get-FileHash file.iso -Algorithm MD5
Get-FileHash file.iso -Algorithm SHA1
Get-FileHash file.iso              # SHA256 is the default

# Any system with OpenSSL
openssl dgst -sha256 file.iso

# Hashing a string: printf adds no newline, echo does
printf '%s' hello | sha256sum      # 2cf24dba5fb0a30e...
echo hello | sha256sum             # 5891b5b522d5df08...

Repare nas duas últimas linhas: o printf não acrescenta quebra de linha e o echo acrescenta, por isso os resumos são diferentes. No PowerShell, Get-FileHash usa SHA256 quando nenhum algoritmo é informado. No navegador, crypto.subtle.digest() aceita SHA-1, SHA-256, SHA-384 e SHA-512, mas não MD5; pedir MD5 lança um NotSupportedError. É por isso que as ferramentas de navegador, incluindo as deste site, calculam o MD5 com uma implementação separada em JavaScript.

Perguntas Frequentes

O SHA-256 é mais lento que o MD5?

Depende do processador. Em um processador sem extensões SHA medimos cerca de 730 MB/s para o MD5 e 460 MB/s para o SHA-256. Processadores com extensões SHA aceleram o SHA-256 o suficiente para que ele possa ser mais rápido que o MD5, e com strings curtas a diferença é desprezível.

O MD5 ainda serve para checksum de arquivos?

Para pegar corrupção acidental, sim, porque ninguém consegue encontrar um arquivo que corresponda a um MD5 dado. Não serve quando um atacante pode ter preparado o arquivo, porque colisões de MD5 são baratas. Use SHA-256 quando o checksum precisa resistir a adulteração.

O SHA-1 está quebrado?

A resistência a colisões dele, sim. Colisões práticas foram demonstradas em 2017 e colisões de prefixo escolhido em 2020, então o SHA-1 não deve ser usado em assinaturas nem certificados. O HMAC-SHA1 e a resistência a pré-imagem não são afetados por esses ataques, mas projetos novos devem usar SHA-256.

Qual hash devo usar para senhas?

Nenhum desses três. Use Argon2id, ou scrypt ou bcrypt se o Argon2id não estiver disponível. Eles são deliberadamente lentos e usam salt, o que torna muito mais caro adivinhar senhas a partir de um banco de dados roubado.