Hashing diz respeito ao processo de criação de uma saída (output) de tamanho fixo a partir de uma entrada (input) de tamanho variável. Isto é feito através do uso de fórmulas matemáticas conhecidas como funções hash (implementadas como algoritmos de hashing).
Embora nem todas as funções de hash envolvam o uso de criptografia, as chamadas funções de hash criptográficas são componentes fundamentais das Criptomoedas. Graças a elas, as blockchains e outros sistemas distribuídos são capazes de atingir níveis significativos de integridade e segurança dos dados.
Tanto as funções de hash convencionais quanto as criptográficas são determinísticas. Ser determinístico significa que enquanto a entrada não mudar, o algoritmo de hash produzirá sempre a mesma saída (também conhecido como digest ou hash).
Tipicamente, os algoritmos de hash criptográfico são projetados como funções unidirecionais, o que significa que eles não podem ser facilmente revertidos sem empregar grandes quantidades de tempo e recursos computacionais.
Em outras palavras, é muito fácil criar a saída a partir da entrada, mas relativamente difícil de ir na direção oposta (gerar a entrada apenas a partir da saída). Em geral, quanto mais difícil a entrada é encontrar, mais seguro é o algoritmo de hashing.
Como Funciona uma Função de Hash?
Diferentes funções de hash produzirão saídas de diferentes tamanhos, mas os possíveis tamanhos de saída para cada algoritmo de hashing são sempre constantes. Por exemplo, o algoritmo SHA-256 só pode produzir saídas de 256 bits, enquanto o SHA-1 sempre gerará uma digest de 160 bits.
Para ilustrar, vamos executar as palavras “Digital” e “digital” através do algoritmo de hashing SHA-256 (que é usado no Bitcoin).
SHA-256
Entrada | Saída (256 bits) |
|
|
|
|
Note que uma pequena mudança (na primeira letra maiúscula) resultou em um valor de hash totalmente diferente. Mas como estamos usando SHA-256, as saídas sempre terão um tamanho fixo de 256 bits (ou 64 caracteres) — independentemente do tamanho da entrada. Além disso, não importa quantas vezes corremos às duas palavras através do algoritmo, às duas saídas permanecerão constantes.
Por outro lado, se executarmos as mesmas entradas através do algoritmo de hash SHA-1, obteríamos os seguintes resultados:
SHA-1
Entrada | Saída (160 bits) |
|
|
|
|
A sigla SHA significa Secure Hash Algorithms (Algoritmos de Hash Seguro). Refere-se a um conjunto de funções criptográficas de hash que incluem os algoritmos SHA-0 e SHA-1 junto com os grupos SHA-2 e SHA-3. O SHA-256 faz parte do grupo SHA-2, junto com o SHA-512 e outras variantes. Atualmente, somente os grupos SHA-2 e SHA-3 são considerados seguras.
Por que eles são Importantes?
As funções convencionais de hash têm uma grande variedade de casos de uso, incluindo buscas em bancos de dados, análise de arquivos grandes, e gerenciamento de dados. Por outro lado, as funções criptográficas de hash são amplamente utilizadas em aplicações de segurança da informação, tais como autenticação de mensagens e impressão digital.
Quando se trata de Bitcoin, as funções criptográficas de hash são uma parte essencial do processo de mineração e também desempenham um papel na geração de novos endereços e chaves.
O verdadeiro poder do hash está em sua capacidade de lidar com enormes quantidades de informação. Por exemplo, é possível executar um grande arquivo ou conjunto de dados através de uma função de hash e depois usar sua saída para verificar rapidamente a precisão e a integridade dos dados.
Isto é possível devido à natureza determinística das funções de hash: a entrada sempre resultará em uma saída simplificada e condensada (hashed). Esta técnica evita a necessidade de “lembrar” e armazenar grandes quantidades de dados.
O hash é particularmente útil no contexto da tecnologia de cadeia de blocos. A cadeia de bloco Bitcoin tem várias operações que envolvem hashing, a maioria delas processo de mineração. De fato, quase todos os protocolos de moeda digital dependem do hashing para ligar e condensar grupos de transações em blocos e também para produzir ligações criptográficas entre cada bloco, criando efetivamente uma cadeia de blocos.
Funções de Hash Criptográficas
Como explicado anteriormente, uma função de hash que emprega técnicas criptográficas pode ser definida como uma função de hash criptográfico. Em geral, a quebra de uma função de hash criptográfico requer milhares de tentativas de força bruta.
Para “reverter” uma função de hash criptográfica, seria necessário adivinhar qual foi a entrada através de tentativa e erro até que finalmente se consiga gerar a saída correspondente. Entretanto, há também a possibilidade de que diferentes entradas possam produzir exatamente a mesma saída. Neste caso, o que é chamado de “colisão” ocorre.
Tecnicamente, uma função de hash criptográfico deve ter três propriedades para ser considerada efetivamente segura. Estas propriedades podem ser chamadas de “resistência à colisão”, “resistência à pré-imagem” e “resistência à segunda pré-imagem”.
Antes de discutir cada propriedade, vamos resumir sua lógica em três frases curtas.
- Resistência à colisão: inviável encontrar duas entradas distintas que produzem o mesmo hash que uma saída.
- Resistência de pré-imagem: inviável para “reverter” a função de hash (encontrar a entrada de uma determinada saída).
- Segunda resistência de pré-imagem: não é possível encontrar qualquer segunda entrada que colida com uma determinada entrada.
Resistência a Colisões
Como mencionado, uma colisão ocorre quando diferentes entradas (inputs) produzem exatamente o mesmo hash. Portanto, uma função de hash é considerada resistente à colisão até que alguém a encontre. Note que sempre haverá colisões para qualquer função de hash porque as possíveis entradas são infinitas, enquanto as possíveis saídas são finitas.
Por outro lado, uma função de hash é resistente a colisões quando a possibilidade de encontrar uma colisão é tão baixa que exigiria milhões de anos de cálculos computacionais. Portanto, embora não haja funções de hash completamente imunes à colisão, algumas delas são suficientemente sólidas para serem consideradas resistentes (por exemplo, o algoritmo SHA-256).
Entre os muitos algoritmos SHA, os grupos SHA-0 e SHA-1 são julgados inseguros porque já foram encontradas colisões. Na atualidade, os grupos SHA-2 e SHA-3 são considerados resistentes a colisões.
Resistência à Pré-imagem
A propriedade de resistência pré-imagem está relacionada com o conceito de funções unidirecionais. Uma função hash é considerada resistente à pré-imagem quando há uma probabilidade muito baixa de que alguém encontre a entrada que gerou uma saída específica.
Note que esta propriedade difere da anterior porque um agente, atacando este hash, estaria tentando adivinhar qual era a entrada ao olhar para uma saída específica. Uma colisão, por outro lado, ocorre quando alguém encontra dois inputs diferentes que geram a mesma saída, não importando quais inputs foram utilizados.
A propriedade da resistência de pré-imagem é valiosa para proteger os dados porque um simples hash de uma mensagem pode provar sua autenticidade, sem a necessidade de revelar as informações que ela contém. Na prática, muitos provedores de serviços e aplicações web armazenam e utilizam hashes gerados a partir de senhas, ao invés de simples senhas de texto.
Resistência à Segunda Pré-imagem
Para simplificar, podemos dizer que a segunda resistência de pré-imagem está em algum lugar entre as outras duas propriedades. Um segundo ataque de pré-imagem ocorre quando alguém é capaz de encontrar uma entrada específica que gera o mesmo resultado de saída que outra entrada já conhecida.
Em outras palavras, um segundo ataque de pré-imagem envolve encontrar uma colisão, mas em vez de procurar dois inputs aleatórios que geram o mesmo hash, eles procuram por um input que gera o mesmo hash que já foi gerado por outro input específico.
Portanto, qualquer função de hash resistente a colisões também é resistente a ataques de segunda pré-imagem, já que este tipo de ataque sempre envolverá uma colisão. Entretanto, ainda é possível realizar um ataque pré-imagem em uma função resistente à colisão, uma vez que isto envolve encontrar uma única entrada gerada a partir de uma única saída.
Mineração
Há muitas etapas na mineração Bitcoin que envolvem funções de hash, tais como verificar saldos, ligar entradas e saídas de transações, e fazer transações de hash dentro de um bloco para formar uma Merkle Tree. Mas um dos principais fatores que torna a cadeia de bloco Bitcoin segura é o fato de que os mineiros precisam realizar milhares de operações de hashing para finalmente encontrar uma solução válida para o próximo bloco.
Mais especificamente, um mineiro tem que tentar várias entradas diferentes ao criar um valor de hash para seu bloco candidato. Na verdade, eles só poderão validar seu bloco se gerarem um hash de saída que comece com um certo número de zeros. O número de zeros é o que determina a dificuldade da mineração, e varia de acordo com a taxa de hash dedicada à rede.
Assim sendo, a taxa de hash representa quanto poder computacional está sendo empregado na mineração de Bitcoin. Se a taxa de hash da rede aumentar, o protocolo Bitcoin ajustará automaticamente a dificuldade da mineração para que o tempo médio necessário para minerar um bloco permaneça próximo a 10 minutos.
Por outro lado, se vários mineiros decidirem interromper a mineração, fazendo com que a taxa de hash caia significativamente, a dificuldade de mineração será ajustada, facilitando o processo de mineração (até que o tempo médio por bloco retorne a 10 minutos).
Note que os mineiros não precisam encontrar colisões porque há vários hashes que eles podem gerar como saída (output) válida (começando com um certo número de zeros). Portanto, existem múltiplas soluções possíveis para um determinado bloco, e os mineiros só precisam encontrar uma delas — de acordo com o limite determinado pela dificuldade da mineração.
Como a mineração de Bitcoin é uma tarefa de alto custo, os mineiros não têm motivos para enganar o sistema, pois isso acarretaria perdas financeiras significativas. Quanto mais mineiros se juntam a uma cadeia de blocos, maior e mais forte ela se torna.
Conclusão
Não há dúvida de que as funções de hash são ferramentas essenciais na ciência da computação, especialmente quando se trata de enormes quantidades de dados. Quando combinados com criptografia, os algoritmos de hash podem ser muito versáteis, oferecendo segurança e autenticação de muitas maneiras diferentes.
Assim, as funções criptográficas de hash são vitais para quase todas as redes de moeda digital, portanto, compreender suas propriedades e mecanismos de trabalho é certamente útil para qualquer pessoa interessada na tecnologia de cadeia de blocos.