Funções Hash e o Bitcoin

[Transcrição do vídeo abaixo]

Pessoal, aqui é Daniel Scocco do canal criptos.com.br e hoje eu vou falar um pouco sobre hash functions ou, funções hash, em português, que é um conceito muito importante na área de criptografia e também é usado em diversas partes do protocolo da rede Bitcoin e de outras criptomoedas também.

Uma função hash nada mais é do que um algoritmo que vai mapear dados de tamanho variável em dados de tamanho fixo. Por exemplo, eu posso ter aqui vários nomes, nomes de usuários e eu vou mapear esses nomes em números de 0 a 15. Uma construção como essa, eu poderia usar por exemplo em um banco de dados para tornar a ida até o banco de dados para buscar as informações referente a cada usuário mais rápida e mais eficiente. Então, ao invés de eu ficar buscando nome por nome, coluna por coluna no banco, eu simplesmente uso uma função hash para converter esse nome aqui no valor 01, por exemplo, e uma vez que esse usuário chegar no sistema, eu sei que todos os dados referentes ao perfil dele estão na posição 01 no meu sistema de arquivos. 

Como que esse algoritmo funciona? Vai depender da implementação. Vou dar um exemplo simples aqui do que poderia estar acontecendo. No fundo é uma função matemática. O meu algoritmo de hash poderia converter cada uma das letras no seu valor de acordo com a posição no alfabeto e somar tudo. Então Maria, se eu aplicasse essa minha função hash básica aí que eu acabei de dar o exemplo, eu pegaria o M, terei o valor 13, o A valor 1, o R valor 18, o I valor 9 e o A valor 1 de novo. A soma de tudo isso é 42 e se eu quiser que esse hash fique dentro de um certo valor, por exemplo somente de 0 a 15, basta eu aplicar a função de módulo. Então 42 módulo 16, o resultado é 10. Maria entraria aqui na posição 10. 

Como vocês estão vendo aqui, é possível que 2 nomes ou 2 Strings, 2 sequências de caracteres, ao passarem pela função hash, elas produzam o mesmo valor, o mesmo hash. Isso aqui é chamado de colisão, não necessariamente um problema. No caso de um banco de dados, dá para resolver isso aqui facilmente, colocando os dados referentes a esses dois usuários nessa posição 2 aqui. Então seria por exemplo uma lista de perfis de usuários em cada uma dessas posições. 

Bom, vamos entender um pouco mais quais são as propriedades das funções hash e quais são os usos também dessas funções. Como eu falei já no exemplo anterior, uma função hash nada mais é do que um algoritmo que mapeia dados de tamanho variável em dados de tamanho fixo. Ou seja, o input dessa função pode ser qualquer string praticamente, qualquer sequência de caracteres, de bits. O output, ele vai ter sempre um tamanho fixo que geralmente vai variar de acordo com o algoritmo que eu estiver usando, mas por exemplo poderia ser 128 bits. Então eu vou colocar qualquer string e minha função hash cospe fora 128 bits. 

Também precisa existir um algoritmo eficiente para fazer esse mapeamento e essa função também deve ser determinista. O que quer dizer isso? Que o mesmo input vai sempre produzir o mesmo output, ou seja, toda vez que eu jogar, por exemplo, Maria na minha função hash, o output vai ser sempre esse hash aqui, que é um número hexadecimal aqui. Quais são os usos das funções hash? Primeiro uso é para você representar de uma forma mais concisa um certo conjunto de dados. Em inglês isso aqui é chamado de digest ou message digest, seria como se fosse uma forma de resumir os dados e isso é muito usado para assinaturas digitais e assinaturas criptográficas. Por que os algarismos das assinaturas eles são computacionalmente caros, então muitas vezes vai ser mais eficiente você primeiro calcular o hash do que você está querendo assinar, e depois você assinar esse hash e o efeito final acaba sendo o mesmo. 

As funções hash também são usadas para você achar dados duplicados em um número grande ou desorganizado de dados, uma vez que, como eu falei, como elas são deterministas, 2 dados se eles forem duplicados, eles vão produzir o mesmo hash, então basta você comparar o hash desses dados. O exemplo anterior também mostrou como as funções hash podem ser usadas em bancos de dados para deixar a busca por informação mais rápida e mais eficiente e por fim eles também podem ser usados para se verificar a integridade dos dados da mensagem. Por exemplo para se assegurar que a mensagem que chegou no destinatário é a mesma que saiu  do remetente. 

Isso aqui que eu falei até agora são funções hash genéricas, que são usadas em Ciência da Computação e em programas. Aí também existe um subconjunto das funções hash, que são funções hash criptográficas, usadas na criptografia e elas precisam ter, atender alguns outros requisitos que não os que eu já mencionei acima. O primeiro deles é que essa função precisa ser isenta de colisões. Colisões, como eu falei já, é quando dois inputs, eles vão mapear para um mesmo hash, para um mesmo output. Por exemplo, aqui eu tenho Maria, que eu joguei na minha função. O hash que saiu fora foi esse aqui. Se eu jogar João e sair o mesmo hash, isto aqui é uma colisão. E para uma função hash criptográfica, isto aqui não pode acontecer. 

Na realidade, não é que essas funções vão ser ausentes de colisões, porque uma vez que o input pode ser qualquer string e o output é fixo, por exemplo 128bits, obviamente o número de strings possíveis aqui no input é muito maior do que o número de strings possíveis no output, então inevitavelmente eu vou ter algumas colisões. O que essa função tem que ser é resistente. Ou seja, estatisticamente a probabilidade de eu conseguir achar uma colisão tem ser muito pequena. Tanto para isso não acontecer acidentalmente, quanto para que uma pessoa, um hacker, uma pessoa mal-intencionada que está querendo fraudar algum sistema criptográfico, ela não deve conseguir, mesmo colocando muito esforço computacional, ela não deve conseguir achar 2 strings, 2 inputs que vão produzir o mesmo output. 

O segundo requisito de uma função hash criptográfica é que ela seja não reversível. Ou seja, uma pessoa mal intencionada olhando somente o hash, ela não deve conseguir chegar no input, na string que foi usada para gerar esse hash, senão teriam aí vulnerabilidades. 

E por fim é interessante que essa função tenha um efeito avalanche. O que quer dizer isso? Que pequenas mudanças no input tem que produzir grandes mudanças no output. Por exemplo se o input for Maria e produzir esse hash, uma vez que eu mudei esse input para Mário, ou seja, mudei uma letra só, o hash teria que vir uma coisa totalmente não relacionada ao hash de Maria. Como você pode ver, o número hexadecimal que não tem nada a ver com o número que foi o output de Maria.

Deixe uma resposta

O seu endereço de e-mail não será publicado.