Funções criptográficas de hash são basicamente alicerces fundamentais
que são usados dentro de vários algoritmos de criptografia e protocolos.
Nós temos um grande número de aplicações importantes
no contexto de segurança da informação como um todo.
Alguns dos algoritmos mais conhecidos nessa categoria,
conhecidos como funções criptográficas de hash,
incluem MD5, e ele também tem predecessores como MD4 e outros;
bem como os algoritmos SHA-256,
e, na verdade, SHA-256 é precedido por outros algoritmos como SHA-1
e assim por diante,
e também há alguns algoritmos que talvez você tenha ouvido falar,
talvez eles sejam menos conhecidos, mas temos RIPEMD e BLAKE e Skein e outros.
Bem, funções criptográficas de hash são basicamente
usadas como partes críticas de várias aplicações
e, a primeira aplicação que motivou,
a primeira aplicação histórica desses tipos de funções de hash
foi no contexto conhecido como assinatura digital.
E assinatura digital é usada em tantas aplicações criptográficas diferentes hoje,
ela é o pilar de muitos protocolos de e-commerce,
é usada para fazer coisas como geração de Bitcoin por exemplo.
Funções criptográficas de hash são usadas em protocolos de autenticação de mensagens
na geração de números pseudo-aleatórios e na segurança de senhas
até mesmo em criptografia em certo grau
e, na verdade, além de seu uso em assinaturas digitais,
essas funções de hash são também usadas em outros lugares do protocolo Bitcoin.
Então, antes de tudo deixe-me falar sobre o que uma função criptográfica de hash é.
E, é claro, como o próprio nome implica, a primeira coisa, ela é uma função de hash
e por função de hash eu quero dizer que ela vai receber uma entrada,
ela é uma função matemática, uma transformação se preferir,
que recebe uma entrada particular, e chamamos essa entrada de uma "mensagem"
e a mensagem pode ser de um tamanho arbitrário
e a função de hash basicamente aplica uma transformação matemática,
talvez um conjunto de transformações matemáticas, nessa entrada
para produzir uma única saída.
Nós normalmente chamamos essa saída de resumo, entretanto às vezes você verá essa
saída sendo referida como uma etiqueta, ou uma hash, ou uma impressão digital;
mas resumo é um dos nomes mais comuns.
E, na verdade, MD5 - que foi uma das primeiras funções de hash - significa
"Message Digest 5" (Resumo da Mensagem 5)
e MD4 é "Message Digest 4" (Resumo da Mensagem 4) e assim por diante.
A mensagem, como eu mencionei breviamente, pode ser de um tamanho arbitrário
pode ser tão longa quanto quiser, ou pode ser tão curta quanto quiser,
mas a saída, o tamanho do resumo vai ser de um tamanho fixo.
Por exemplo, no contexto de uma função de hash como, vamos dizer, SHA-256,
o resumo vai ter exatamente 256 bits de tamanho.
Então vai ter uma saída de tamanho fixo mas uma entrada de tamanho arbitrário
E a outra coisa que quero ressaltar sobre essas funções criptográficas de hash é
que a função é uma função determinística, e por isso eu quero dizer que
a saída sempre será a mesma para uma entrada específica.
Então se você tem uma entrada específica, vai ver a mesma exata saída.
Você não vai ter uma situação em que dado uma entrada terá duas possíveis saídas.
Vai ser consistente.
Bem, funções de hash tradicionais vem sendo usadas em Ciência da Computação
há bastante tempo e elas são usadas em várias aplicações computacionais.
Você talvez tenha ouvido sobre uma função hash usada para fazer uma tabela hash.
Mas o tipo de funções hash que são usadas em tabelas hash, e eu quero destacar isso,
não são necessariamente o mesmo que funções criptográficas de hash.
O qualificador 'criptográficas' aqui é muito importante.
E geralmente significa que essa função hash tem que ter um certo conjunto de
objetivos críticos de design e talvez algumas propriedades particulares em mente
que a faça adequada para o uso em aplicações que usem criptografia
onde talvez segurança ou privacidade, ou confidencialidade ou autenticação
é uma preocupação séria.
Então, primeiro e antes de tudo em descrevendo as propriedades de alguém
é que, e talvez isso nem precise ser dito,
uma das propriedades que você quer em uma função criptográfica de hash
é que ela deveria ser computacionalmente - computacionalmente eficiente.
E com isso quero dizer que ela não deveria levar muito tempo
para computar a saída de uma determinada entrada
Se você recebe uma mensagem e quer aplicar um conjunto de transformações nesta
mensagem para obter um resumo, esse conjunto de transformações não deveria
tomar muito tempo para ser implementado em um computador, deveria ser bem rápido.
E isso quase nem precisava ser dito mas acho importante reforçar e destacar
porque eu já vi pessoas fazerem implementações grosseiramente ineficientes
de funções de hash algumas vezes e estas não seriam consideradas adequadas
no contexto de uma típica função criptográfica de hash que é usada para
aplicações criptográficas.
E a segunda propriedade que geralmente se precisa, especialmente no contexto de
assinatura digital, é: você quer que seja o caso de ser difícil que duas entradas
sejam mapeadas realmente para a mesma entrada. Duas entradas distintas
cujos resumos correspondentes sejam idênticos.
E essa propriedade geralmente é chamada de colisão, resistência à colisões.
Isso significa que é difícil achar um par de entradas que colidam.
Em outras palavras, se temos duas entradas vamos dizer uma mensagem M1 e uma M2.
Suas saídas da aplicação da função de hash não deveriam ser a mesma.
Você nunca teria o caso em que a saída de M1 e M2 da aplicação da função de hash
são iguais. Nunca deveria ser igual. Deve sempre ser diferente.
Eu deveria voltar um passo e destacar que, é claro, na prática,
dado que a mensagem pode ser de um tamanho arbitrário e a saída é de um tamanho fixo,
não é mateticamente possível garantir que a saída sempre será diferente
para duas mensagens distintas.
Mas o que você geralmente quer não é que as saídas sejam necessariamente diferentes
mas que seja difícil para achar mensagens distintas que produzem a mesma saída.
Nós sabemos que elas existem em virtude do fato que mensagens podem ser mapeadas
em apenas um número finito e pequeno
(ou relativamente um número pequeno se comparado ao número de mensagens)
um número pequeno de possíveis valores resumo.
Mas fora essa consideração, deveria ser difícil, deveria levar muito tempo,
e por muito tempo eu quero dizer astronomicamente muito tempo para achar
duas mensagens distintas que resultariam na mesma saída aplicando a função de hash.
Bem, a terceira coisa que eu quero ressaltar é que em vários casos
você pode também querer, no contexto das funções de hash, que a função seja capaz
de esconder informações sobre as entradas.
Em outras palavras, dado a saída, deveria ser difícil coletar qualquer informação
útil ou interessante sobre a entrada. Qualquer coisa, qualquer detalhe relevante
e não quero dizer apenas a entrada inteira mas até mesmo uma coisa tão simples quanto
"a entrada era um número par ou um número ímpar?"
E isso deveria ser o tipo de coisa que é difícil inferir quando você vê a saída.
Até mesmo algo tão simples quanto a paridade ou imparidade da entrada.
Agora, a quarta propriedade que quero ressaltar
é que você geralmente quer que a saída seja bem distribuída.
Em outras palavras, a saída deve parecer aleatória.
Deve parecer como se fosse um conjunto de jogadas de moeda feitas de nenhuma forma
previsível em que a saída foi criada.
E isso significa que é quase como se você jogasse várias moedas para fazer a saída.
Deve parecer aleatório.
Você pode pensar em funções criptográficas de hash como talvez o equivalente
matemático ou análogo de um moedor de carne.
Ele pode receber entradas e aplicar essas transformações matemáticas nelas
de modo que a saída pareça, para todos os propósitos, completamente aleatória
e sem relação com a entrada original.
Eu quero fazer algumas pequenas observações sobre essas propriedades.
E antes de tudo, elas são inter-relacionadas - por exemplo,
se você tem uma situação onde a saída não aparenta mesmo ter relação com a entrada,
e a saída também parece aleatória,
então isso vai te dar na verdade, em certo grau, uma grande resistência a colisões
porque apenas o fato de que você não pode prever a saída e o fato de que ela esconde
toda essa informação implica que vai ser difícil achar duas entradas distintas
que são mapeadas para a mesma saída.
E então, às vezes você consegue uma propriedade em troca das outras.
A segunda coisa que eu quero ressaltar é que geralmente essas propriedades
na prática, ou até mesmo em matemática subjacente, são coisas que você espera por
mas que você não pode sempre garantir que elas serão sempre válidas.
E talvez seja completamente possível que você poderia desenvolver uma função hash
que você pensa ser completamente resistente à colisões
mas alguém pode aparecer e, daqui a um ano inventar uma maneira mais inteligente
para achar colisões.
Talvez ele tenha descoberto um jeito que não involva fazer uma busca de força bruta
E acontece que criptógrafos, para o bem ou para o mal, atualmente não têm nenhuma
técnica matemática, eles não desenvolveram técnicas capazes de
contornar algumas dessas limitações.
Assim, nós frequentemente tomamos como base de quanto esses esquemas são seguros
pelo tempo que eles vêm sendo utilizados.
Agora eu também quero destacar uma última coisa, essa forma como tratei o assunto
não é de forma alguma matematicamente rigoroso.
Existem métodos muito mais precisos de descrever essas propriedades.
Mas eu espero que esse vídeo talvez te dê uma noção geral
do que é necessário a uma função criptográfica de hash
sem ficar chato entrando em detalhes formais matemáticos.
[Legendado por Alberto Oliveira]