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]