A criptografia é a ciência de proteger informação de modo a que só as partes previstas a possam ler, verificar ou aceitar como autêntica. Está por detrás de quase tudo o que acontece online, desde o início de sessão no banco até à confirmação de que um ficheiro descarregado chegou intacto. Esta secção explica as ideias centrais e coloca o hashing e as funções de hash no centro, porque foi precisamente aí que a nossa investigação deixou marca: em 2017 produzimos a primeira colisão prática de SHA-1 e demonstrámos que uma função de hash muito usada estava quebrada não em teoria, mas na realidade.

O que uma função de hash criptográfica faz

Uma função de hash criptográfica recebe dados de qualquer tamanho e devolve uma sequência curta de bytes de comprimento fixo, normalmente apresentada em hexadecimal. A essa sequência costuma chamar-se resumo, ou digest. A ideia é simples de descrever: para a mesma entrada, obtém-se sempre a mesma saída, mas a partir da saída não há forma viável de recuperar a entrada original. É um sentido único.

Pense num hash como uma impressão digital de dados. Dois ficheiros idênticos produzem o mesmo resumo, e qualquer diferença, por mínima que seja, produz um resumo completamente distinto. Isto permite comparar, identificar e verificar dados sem precisar de guardar ou transmitir os dados em si.

Há um conjunto de propriedades que separam uma boa função de hash criptográfica de um cálculo qualquer. É determinística, devolvendo sempre o mesmo valor para a mesma entrada. É rápida de calcular. É resistente à pré-imagem, ou seja, a partir de um resumo não se consegue, na prática, encontrar uma entrada que o gere. É resistente a colisões, o que significa que não se conseguem encontrar duas entradas diferentes com o mesmo resumo. E exibe o efeito de avalanche: mudar um único bit da entrada altera cerca de metade dos bits da saída, tornando o novo resumo aparentemente sem relação com o anterior. O artigo dedicado às funções de hash percorre cada uma destas propriedades em detalhe.

Hashing não é cifragem

Vale a pena fixar cedo a diferença entre hashing e cifragem, porque os dois são frequentemente confundidos.

A cifragem é reversível. Cifram-se dados com uma chave e quem possuir a chave correta volta a torná-los legíveis. O propósito da cifragem é exatamente esse: recuperar a mensagem mais tarde.

O hashing é um processo de sentido único. Não há chave e não existe forma de inverter o resumo para reaver o original. Usa-se hashing quando se quer verificar algo sem guardar nem transmitir a coisa em si. Uma regra prática ajuda a distinguir: a cifragem guarda um segredo que se pretende revelar depois, enquanto o hashing cria uma impressão digital que nunca se quer inverter.

A família SHA, em traços largos

A maioria das funções de hash que aparecem na prática pertence a um pequeno grupo de desenhos conhecidos. A sigla SHA significa Secure Hash Algorithm, e a designação cobre várias gerações com níveis de segurança muito diferentes.

MD5 não pertence à família SHA, mas surge sempre na mesma conversa. Produz um resumo de 128 bits e foi outrora omnipresente. Hoje considera-se completamente quebrada, ao ponto de se gerarem colisões em segundos num portátil. Como simples soma de verificação, sem qualquer pretensão de segurança, ainda aparece, mas nunca deve ser usada onde um atacante possa lucrar com a falsificação de uma correspondência.

SHA-1 devolve um resumo de 160 bits e foi, durante anos, o cavalo de batalha da web. A nossa investigação, batizada SHAttered, demonstrou a primeira colisão real com dois ficheiros PDF diferentes que produziam o mesmo valor de SHA-1. O caso está descrito a fundo no artigo sobre a colisão de SHA-1, e foi esse resultado que levou a indústria a aposentar o SHA-1 em certificados, assinaturas e sistemas de controlo de versões.

SHA-256 pertence à família SHA-2 e é, atualmente, o padrão para a maioria das aplicações. Com 256 bits de saída e sem ataques práticos conhecidos, sustenta certificados TLS, a assinatura de software e a prova de trabalho da Bitcoin. O artigo sobre SHA-256 explica onde se encaixa e por que motivo continua a resistir.

SHA-3 é um padrão mais recente, assente numa estrutura interna completamente diferente da do MD5, SHA-1 e SHA-2. Foi normalizado como reserva, para que uma eventual fraqueza futura no SHA-2 não deixasse todos sem alternativa.

Função de hash Tamanho do resumo Estado
MD5 128 bits Quebrada, a evitar
SHA-1 160 bits Quebrada (colisão encontrada), aposentada
SHA-256 (SHA-2) 256 bits Segura, recomendada
SHA-3 224 a 512 bits Segura, estrutura alternativa

Por que o hashing sustenta a confiança online

À primeira vista, transformar dados numa impressão digital fixa pode parecer um detalhe técnico menor. Na verdade, é uma das peças que torna a confiança possível em redes onde ninguém conhece pessoalmente ninguém.

As assinaturas digitais, os certificados e as verificações de integridade raramente assinam o documento em si. Assinam o seu resumo. Uma assinatura, um identificador de commit no Git, a impressão digital de um certificado ou a garantia de que um ficheiro não foi alterado reduzem tudo a um hash e confiam que esse hash é único para aquele conteúdo. Daí a importância da resistência a colisões: se dois ficheiros partilharem o mesmo resumo, uma assinatura sobre um vale igualmente para o outro, e a ligação entre o que foi aprovado e o que se recebeu quebra-se em silêncio. É exatamente este o cenário de ataque que torna a quebra do SHA-1 mais do que uma curiosidade académica.

O mesmo princípio aparece em muitos pontos do dia a dia digital:

  • TLS e HTTPS. O cadeado no navegador apoia-se em criptografia assimétrica para autenticar o servidor e negociar uma chave, e em hashes para confirmar que os dados não foram adulterados em trânsito.
  • Palavras-passe. Os serviços sensatos nunca guardam a palavra-passe em si. Guardam um hash com sal, de modo que uma fuga da base de dados não entregue as credenciais reais a um atacante.
  • Bitcoin e blockchains. O SHA-256 encadeia os blocos uns aos outros e protege a mineração, enquanto as assinaturas digitais autorizam cada transação.
  • Integridade de software. As páginas de descarga publicam hashes, e por vezes assinaturas, para que se confirme que um instalador não foi trocado nem corrompido pelo caminho.

O que esta secção cobre

A partir deste centro, quatro artigos aprofundam cada ramo do tema, e todos assentam nos mesmos blocos descritos acima.

O artigo sobre a colisão de SHA-1 conta a história completa do SHAttered, o que é uma colisão e por que motivo a sua existência prática abalou a confiança na assinatura digital. O artigo sobre SHA-256 explica o padrão atual, como se comporta e onde é usado. O texto sobre funções de hash generaliza o conceito, detalhando as propriedades que uma função criptográfica precisa de ter e como difere de um hash comum. E o artigo sobre assinaturas digitais liga tudo, mostrando como o hashing e as chaves assimétricas se combinam para provar autoria e integridade ao mesmo tempo, e por que uma colisão de hash ameaça diretamente essa prova.

Lidos em conjunto, estes textos descrevem a mesma ideia vista de ângulos diferentes: a confiança online não vem de bloquear o acesso aos dados, mas de provar, de forma que qualquer pessoa pode verificar, que os dados são exatamente o que dizem ser.

Perguntas frequentes

O hashing é uma forma de cifragem?

Não. A cifragem é reversível com uma chave, enquanto o hashing é uma impressão digital de sentido único, sem volta. Costumam usar-se em conjunto, mas são ferramentas distintas para problemas distintos.

Porque é que o SHA-1 é considerado quebrado se continua a produzir um resumo?

Continua a gerar uma saída, mas vários investigadores, incluindo a nossa equipa, encontraram forma de produzir duas entradas diferentes com o mesmo valor de SHA-1. A partir do momento em que as colisões se tornam viáveis, deixa de ser possível confiar na função para assinaturas ou certificados, mesmo que ela ainda funcione tecnicamente.

Qual a função de hash que devo usar?

Para a generalidade dos fins, o SHA-256 é a escolha segura por defeito. O SHA-3 é uma alternativa sólida sobre outra estrutura. Para guardar palavras-passe, o ideal é uma função propositadamente lenta e desenhada para esse fim, como bcrypt, scrypt ou Argon2, em vez de um hash rápido aplicado diretamente.