WEBVTT
00:00:00.800 --> 00:00:04.530
Funções criptográficas de hash são
basicamente alicerces fundamentais
00:00:04.530 --> 00:00:08.220
que são usados dentro de vários
algoritmos de criptografia e protocolos.
00:00:08.220 --> 00:00:10.720
Nós temos um grande número
de aplicações importantes
00:00:10.720 --> 00:00:14.490
no contexto de segurança da
informação como um todo.
00:00:14.490 --> 00:00:17.070
Alguns dos algoritmos mais
conhecidos nessa categoria,
00:00:17.070 --> 00:00:19.260
conhecidos como funções
criptográficas de hash,
00:00:19.260 --> 00:00:26.350
incluem MD5, e ele também tem
predecessores como MD4 e outros;
00:00:26.350 --> 00:00:30.070
bem como os algoritmos SHA-256,
00:00:30.070 --> 00:00:35.230
e, na verdade, SHA-256 é precedido
por outros algoritmos como SHA-1
00:00:35.230 --> 00:00:36.930
e assim por diante,
00:00:36.930 --> 00:00:41.070
e também há alguns algoritmos que
talvez você tenha ouvido falar,
00:00:41.070 --> 00:00:46.040
talvez eles sejam menos conhecidos, mas
temos RIPEMD e BLAKE e Skein e outros.
00:00:46.040 --> 00:00:49.000
Bem, funções criptográficas
de hash são basicamente
00:00:49.000 --> 00:00:52.340
usadas como partes críticas
de várias aplicações
00:00:52.340 --> 00:00:54.840
e, a primeira aplicação que motivou,
00:00:54.840 --> 00:00:58.690
a primeira aplicação histórica
desses tipos de funções de hash
00:00:58.690 --> 00:01:03.470
foi no contexto conhecido
como assinatura digital.
00:01:03.470 --> 00:01:07.860
E assinatura digital é usada em tantas
aplicações criptográficas diferentes hoje,
00:01:07.860 --> 00:01:11.510
ela é o pilar de muitos
protocolos de e-commerce,
00:01:11.510 --> 00:01:15.380
é usada para fazer coisas como
geração de Bitcoin por exemplo.
00:01:15.380 --> 00:01:20.500
Funções criptográficas de hash são usadas
em protocolos de autenticação de mensagens
00:01:20.500 --> 00:01:24.340
na geração de números pseudo-aleatórios
e na segurança de senhas
00:01:24.340 --> 00:01:26.420
até mesmo em criptografia em certo grau
00:01:26.420 --> 00:01:30.840
e, na verdade, além de seu
uso em assinaturas digitais,
00:01:30.840 --> 00:01:35.410
essas funções de hash são também usadas
em outros lugares do protocolo Bitcoin.
00:01:35.410 --> 00:01:40.040
Então, antes de tudo deixe-me falar sobre
o que uma função criptográfica de hash é.
00:01:40.040 --> 00:01:44.410
E, é claro, como o próprio nome implica,
a primeira coisa, ela é uma função de hash
00:01:44.410 --> 00:01:48.710
e por função de hash eu quero dizer
que ela vai receber uma entrada,
00:01:48.710 --> 00:01:51.800
ela é uma função matemática,
uma transformação se preferir,
00:01:51.800 --> 00:01:56.780
que recebe uma entrada particular,
e chamamos essa entrada de uma "mensagem"
00:01:56.780 --> 00:01:59.600
e a mensagem pode ser
de um tamanho arbitrário
00:01:59.600 --> 00:02:04.550
e a função de hash basicamente aplica
uma transformação matemática,
00:02:04.550 --> 00:02:07.730
talvez um conjunto de transformações
matemáticas, nessa entrada
00:02:07.730 --> 00:02:09.290
para produzir uma única saída.
00:02:09.290 --> 00:02:13.900
Nós normalmente chamamos essa saída de
resumo, entretanto às vezes você verá essa
00:02:13.900 --> 00:02:19.380
saída sendo referida como uma etiqueta,
ou uma hash, ou uma impressão digital;
00:02:19.380 --> 00:02:22.130
mas resumo é um dos
nomes mais comuns.
00:02:22.130 --> 00:02:27.300
E, na verdade, MD5 - que foi uma das
primeiras funções de hash - significa
00:02:27.300 --> 00:02:29.440
"Message Digest 5" (Resumo da Mensagem 5)
00:02:29.440 --> 00:02:32.720
e MD4 é "Message Digest 4" (Resumo da
Mensagem 4) e assim por diante.
00:02:33.270 --> 00:02:36.920
A mensagem, como eu mencionei breviamente,
pode ser de um tamanho arbitrário
00:02:36.920 --> 00:02:40.270
pode ser tão longa quanto quiser,
ou pode ser tão curta quanto quiser,
00:02:40.270 --> 00:02:45.920
mas a saída, o tamanho do resumo
vai ser de um tamanho fixo.
00:02:45.920 --> 00:02:50.780
Por exemplo, no contexto de uma função
de hash como, vamos dizer, SHA-256,
00:02:50.780 --> 00:02:55.940
o resumo vai ter exatamente
256 bits de tamanho.
00:02:55.940 --> 00:03:01.350
Então vai ter uma saída de tamanho fixo
mas uma entrada de tamanho arbitrário
00:03:01.350 --> 00:03:05.110
E a outra coisa que quero ressaltar sobre
essas funções criptográficas de hash é
00:03:05.110 --> 00:03:09.750
que a função é uma função determinística,
e por isso eu quero dizer que
00:03:09.750 --> 00:03:12.370
a saída sempre será a mesma
para uma entrada específica.
00:03:12.370 --> 00:03:15.660
Então se você tem uma entrada específica,
vai ver a mesma exata saída.
00:03:15.660 --> 00:03:19.640
Você não vai ter uma situação em que dado
uma entrada terá duas possíveis saídas.
00:03:19.640 --> 00:03:21.060
Vai ser consistente.
00:03:21.890 --> 00:03:26.720
Bem, funções de hash tradicionais vem
sendo usadas em Ciência da Computação
00:03:26.720 --> 00:03:30.300
há bastante tempo e elas são usadas
em várias aplicações computacionais.
00:03:30.300 --> 00:03:34.730
Você talvez tenha ouvido sobre uma função
hash usada para fazer uma tabela hash.
00:03:34.730 --> 00:03:40.390
Mas o tipo de funções hash que são usadas
em tabelas hash, e eu quero destacar isso,
00:03:40.390 --> 00:03:44.640
não são necessariamente o mesmo
que funções criptográficas de hash.
00:03:44.640 --> 00:03:48.360
O qualificador 'criptográficas'
aqui é muito importante.
00:03:48.360 --> 00:03:54.130
E geralmente significa que essa função
hash tem que ter um certo conjunto de
00:03:54.130 --> 00:03:58.300
objetivos críticos de design e talvez
algumas propriedades particulares em mente
00:03:58.300 --> 00:04:03.940
que a faça adequada para o uso em
aplicações que usem criptografia
00:04:03.940 --> 00:04:08.470
onde talvez segurança ou privacidade,
ou confidencialidade ou autenticação
00:04:08.470 --> 00:04:10.460
é uma preocupação séria.
00:04:11.350 --> 00:04:14.830
Então, primeiro e antes de tudo em
descrevendo as propriedades de alguém
00:04:14.830 --> 00:04:16.830
é que, e talvez isso nem precise ser dito,
00:04:16.830 --> 00:04:20.120
uma das propriedades que você quer
em uma função criptográfica de hash
00:04:20.120 --> 00:04:24.550
é que ela deveria ser computacionalmente -
computacionalmente eficiente.
00:04:24.550 --> 00:04:27.400
E com isso quero dizer que
ela não deveria levar muito tempo
00:04:27.400 --> 00:04:31.200
para computar a saída de
uma determinada entrada
00:04:31.200 --> 00:04:35.400
Se você recebe uma mensagem e quer aplicar
um conjunto de transformações nesta
00:04:35.400 --> 00:04:39.840
mensagem para obter um resumo, esse
conjunto de transformações não deveria
00:04:39.840 --> 00:04:43.800
tomar muito tempo para ser implementado
em um computador, deveria ser bem rápido.
00:04:43.800 --> 00:04:47.320
E isso quase nem precisava ser dito mas
acho importante reforçar e destacar
00:04:47.320 --> 00:04:50.790
porque eu já vi pessoas fazerem
implementações grosseiramente ineficientes
00:04:50.790 --> 00:04:54.260
de funções de hash algumas vezes e estas
não seriam consideradas adequadas
00:04:54.260 --> 00:04:58.270
no contexto de uma típica função
criptográfica de hash que é usada para
00:04:58.270 --> 00:05:00.190
aplicações criptográficas.
00:05:01.000 --> 00:05:05.030
E a segunda propriedade que geralmente
se precisa, especialmente no contexto de
00:05:05.030 --> 00:05:10.780
assinatura digital, é: você quer que seja
o caso de ser difícil que duas entradas
00:05:10.780 --> 00:05:14.540
sejam mapeadas realmente para a mesma
entrada. Duas entradas distintas
00:05:14.540 --> 00:05:17.840
cujos resumos correspondentes
sejam idênticos.
00:05:17.840 --> 00:05:23.930
E essa propriedade geralmente é chamada de
colisão, resistência à colisões.
00:05:23.930 --> 00:05:28.780
Isso significa que é difícil achar
um par de entradas que colidam.
00:05:28.780 --> 00:05:34.400
Em outras palavras, se temos duas entradas
vamos dizer uma mensagem M1 e uma M2.
00:05:34.400 --> 00:05:40.150
Suas saídas da aplicação da função de hash
não deveriam ser a mesma.
00:05:40.150 --> 00:05:47.850
Você nunca teria o caso em que a saída
de M1 e M2 da aplicação da função de hash
00:05:47.850 --> 00:05:51.770
são iguais. Nunca deveria ser igual.
Deve sempre ser diferente.
00:05:52.220 --> 00:05:57.590
Eu deveria voltar um passo e
destacar que, é claro, na prática,
00:05:57.590 --> 00:06:04.860
dado que a mensagem pode ser de um tamanho
arbitrário e a saída é de um tamanho fixo,
00:06:04.860 --> 00:06:11.420
não é mateticamente possível garantir
que a saída sempre será diferente
00:06:11.420 --> 00:06:12.930
para duas mensagens distintas.
00:06:12.930 --> 00:06:16.840
Mas o que você geralmente quer não é que
as saídas sejam necessariamente diferentes
00:06:16.840 --> 00:06:21.340
mas que seja difícil para achar mensagens
distintas que produzem a mesma saída.
00:06:21.340 --> 00:06:25.420
Nós sabemos que elas existem em virtude do
fato que mensagens podem ser mapeadas
00:06:25.420 --> 00:06:27.690
em apenas um número finito e pequeno
00:06:27.690 --> 00:06:31.070
(ou relativamente um número pequeno se
comparado ao número de mensagens)
00:06:31.070 --> 00:06:34.040
um número pequeno de
possíveis valores resumo.
00:06:34.040 --> 00:06:38.810
Mas fora essa consideração, deveria ser
difícil, deveria levar muito tempo,
00:06:38.810 --> 00:06:43.160
e por muito tempo eu quero dizer
astronomicamente muito tempo para achar
00:06:43.160 --> 00:06:49.630
duas mensagens distintas que resultariam
na mesma saída aplicando a função de hash.
00:06:50.790 --> 00:06:54.280
Bem, a terceira coisa que eu quero
ressaltar é que em vários casos
00:06:54.280 --> 00:06:58.550
você pode também querer, no contexto das
funções de hash, que a função seja capaz
00:06:58.550 --> 00:07:01.530
de esconder informações
sobre as entradas.
00:07:01.530 --> 00:07:08.580
Em outras palavras, dado a saída, deveria
ser difícil coletar qualquer informação
00:07:08.580 --> 00:07:13.450
útil ou interessante sobre a entrada.
Qualquer coisa, qualquer detalhe relevante
00:07:13.450 --> 00:07:17.450
e não quero dizer apenas a entrada inteira
mas até mesmo uma coisa tão simples quanto
00:07:17.450 --> 00:07:19.740
"a entrada era um número par
ou um número ímpar?"
00:07:19.740 --> 00:07:24.400
E isso deveria ser o tipo de coisa que é
difícil inferir quando você vê a saída.
00:07:24.400 --> 00:07:29.850
Até mesmo algo tão simples quanto a
paridade ou imparidade da entrada.
00:07:30.550 --> 00:07:33.070
Agora, a quarta propriedade
que quero ressaltar
00:07:33.070 --> 00:07:37.430
é que você geralmente quer
que a saída seja bem distribuída.
00:07:37.430 --> 00:07:43.750
Em outras palavras, a saída
deve parecer aleatória.
00:07:43.750 --> 00:07:47.750
Deve parecer como se fosse um conjunto de
jogadas de moeda feitas de nenhuma forma
00:07:47.750 --> 00:07:52.790
previsível em que a saída foi criada.
00:07:53.690 --> 00:08:00.470
E isso significa que é quase como se você
jogasse várias moedas para fazer a saída.
00:08:00.470 --> 00:08:02.900
Deve parecer aleatório.
00:08:02.900 --> 00:08:08.200
Você pode pensar em funções criptográficas
de hash como talvez o equivalente
00:08:08.200 --> 00:08:11.070
matemático ou análogo
de um moedor de carne.
00:08:11.070 --> 00:08:15.800
Ele pode receber entradas e aplicar essas
transformações matemáticas nelas
00:08:15.800 --> 00:08:20.550
de modo que a saída pareça, para todos os
propósitos, completamente aleatória
00:08:20.550 --> 00:08:23.160
e sem relação com
a entrada original.
00:08:23.920 --> 00:08:28.130
Eu quero fazer algumas pequenas
observações sobre essas propriedades.
00:08:28.130 --> 00:08:31.730
E antes de tudo, elas são
inter-relacionadas - por exemplo,
00:08:31.730 --> 00:08:37.510
se você tem uma situação onde a saída não
aparenta mesmo ter relação com a entrada,
00:08:37.730 --> 00:08:40.210
e a saída também parece aleatória,
00:08:40.210 --> 00:08:44.830
então isso vai te dar na verdade, em certo
grau, uma grande resistência a colisões
00:08:44.830 --> 00:08:48.790
porque apenas o fato de que você não pode
prever a saída e o fato de que ela esconde
00:08:48.790 --> 00:08:54.270
toda essa informação implica que vai ser
difícil achar duas entradas distintas
00:08:54.270 --> 00:08:55.990
que são mapeadas para a mesma saída.
00:08:55.990 --> 00:08:59.180
E então, às vezes você consegue uma
propriedade em troca das outras.
00:08:59.180 --> 00:09:02.670
A segunda coisa que eu quero ressaltar
é que geralmente essas propriedades
00:09:02.670 --> 00:09:07.960
na prática, ou até mesmo em matemática
subjacente, são coisas que você espera por
00:09:07.960 --> 00:09:11.490
mas que você não pode sempre garantir
que elas serão sempre válidas.
00:09:11.490 --> 00:09:15.450
E talvez seja completamente possível que
você poderia desenvolver uma função hash
00:09:15.450 --> 00:09:18.400
que você pensa ser completamente
resistente à colisões
00:09:18.400 --> 00:09:22.370
mas alguém pode aparecer e, daqui a um ano
inventar uma maneira mais inteligente
00:09:22.370 --> 00:09:24.240
para achar colisões.
00:09:24.240 --> 00:09:28.700
Talvez ele tenha descoberto um jeito que
não involva fazer uma busca de força bruta
00:09:29.370 --> 00:09:34.770
E acontece que criptógrafos, para o bem ou
para o mal, atualmente não têm nenhuma
00:09:34.770 --> 00:09:37.670
técnica matemática, eles não
desenvolveram técnicas capazes de
00:09:37.670 --> 00:09:40.450
contornar algumas dessas limitações.
00:09:40.450 --> 00:09:45.150
Assim, nós frequentemente tomamos como
base de quanto esses esquemas são seguros
00:09:45.150 --> 00:09:47.920
pelo tempo que eles
vêm sendo utilizados.
00:09:47.920 --> 00:09:51.740
Agora eu também quero destacar uma última
coisa, essa forma como tratei o assunto
00:09:51.740 --> 00:09:55.470
não é de forma alguma
matematicamente rigoroso.
00:09:55.470 --> 00:10:01.140
Existem métodos muito mais precisos
de descrever essas propriedades.
00:10:01.140 --> 00:10:05.640
Mas eu espero que esse vídeo
talvez te dê uma noção geral
00:10:05.640 --> 00:10:08.530
do que é necessário a uma função
criptográfica de hash
00:10:08.530 --> 00:10:12.423
sem ficar chato entrando em
detalhes formais matemáticos.
00:10:12.423 --> 00:10:13.123
[Legendado por Alberto Oliveira]