Entre 2013 e 2017 eu atuei como professor regular do curso superior de Análise e Desenvolvimento de Sistemas da Faculdade de Tecnologia de Porto Alegre (FAQI/RS). Uma das disciplinas que lecionei foi a de Segurança da Informação cujo tópico que mais me interessa até hoje é criptografia.
Criptografia (em grego: kryptós, “escondido”, e gráphein, “escrita”) é o estudo dos princípios e técnicas pelas quais a informação pode ser transformada da sua forma original para outra ilegível, de forma que possa ser conhecida apenas por seu destinatário (detentor da “chave secreta”), o que a torna difícil de ser lida por alguém não autorizado. Assim sendo, só o receptor da mensagem pode ler a informação com facilidade. É um ramo da Matemática, parte da Criptologia.
No artigo de hoje quero trazer uma introdução ao assunto, para quem não sabe nada e quer aprender o suficiente para tomar algumas decisões simples no dia a dia como desenvolvedor. Para estudos mais avançados no assunto, recomendo procurar materiais de especialistas focados nisso, geralmente da área de cybersegurança.
Se preferir, você pode assistir ao vídeo abaixo ao invés de ler o artigo.
Vamos lá!
#1 – Cifragem, decifragem e mais
Uma informação não-cifrada que é enviada de uma pessoa (ou organização) para outra é chamada de “texto claro” ou “texto plano” (plaintext). Cifragem é o processo de conversão de um texto claro para um código cifrado e decifragem é o processo contrário, de recuperar o texto original a partir de um texto cifrado. A criptografia moderna é basicamente formada pelo estudo dos algoritmos criptográficos que podem ser implementados em computadores para fazer este processo de cifragem e decifragem de maneira mais otimizada do que Julio César fazia no Império Romano (primeiro registro de criptografia) ou os alemães faziam na Segunda Guerra Mundial com a máquina Enigma (último uso mecânico antes da era dos computadores eletrônicos).
Apesar da crença popular, a criptografia não se resume apenas à cifragem e decifragem para ocultação de mensagens, ela tem quatro objetivos principais:
- Confidencialidade da Mensagem: só o destinatário autorizado deve ser capaz de extrair o conteúdo da mensagem da sua forma cifrada. Além disso, a obtenção de informação sobre o conteúdo da mensagem (como uma distribuição estatística de certos caracteres) não deve ser possível, uma vez que, se o for, torna mais fácil a análise criptográfica;
- Integridade da Mensagem: o destinatário deverá ser capaz de verificar se a mensagem foi alterada durante a transmissão;
- Autenticação do Remetente: o destinatário deverá ser capaz de verificar que se o remetente é realmente quem diz ser;
- Não-repúdio ou Irretratabilidade do remetente: não deverá ser possível ao remetente negar a autoria de sua mensagem.
Nem todos os sistemas ou algoritmos criptográficos são utilizados para atingir todos os objetivos listados acima. Normalmente, existem algoritmos específicos para cada uma destas funções e é justamente por isso que é importante estudá-la antes de sair aplicando algum algoiritmo qualquer em sua aplicação. Mesmo em sistemas criptográficos bem concebidos, bem implementados e usados adequadamente, alguns dos objetivos acima não são práticos (ou mesmo desejáveis) em algumas circunstâncias. Por exemplo, o remetente de uma mensagem pode querer permanecer anônimo, ou o sistema pode destinar-se a um ambiente com recursos computacionais limitados.
É importante citar também que não existe algoritmo de criptografia perfeito, que sirva para qualquer situação ou mesmo que seja inviolável. As características de bons algoritmos levam em conta as tecnologias atuais e de um futuro previsível, o contexto em que será utilizada, ataques práticos e teóricos e mais. No entanto, a segurança da informação como um todo está sempre evoluindo e é uma eterna briga de gato e rato entre quem quer proteger contra quem quer atacar. Além disso, não custa nada lembrar que criptografia é apenas a cereja do bolo quando o assunto é a segurança da sua aplicação e você deve buscar outros meios além desse para protegê-las, continuamente.
Para estudarmos alguns dos principais tipos e seus algoritmos, eu vou começar separando em dois grandes grupos: a criptografia reversível e a criptografia irreversível. Enquanto o primeiro grupo seja o mais comum e fácil de entender (também chamada de criptografia de mão-dupla, pois vai e volta), o segundo costuma causar bastante confusão embora seja tão importante quanto o primeiro (também chamada de criptografia de mão-única, pois apenas cifra).
#2 – Criptografia Reversível
A criptografia reversível começou com as Cifras de César durante o Império Romano. O imperador Júlio Cesar queria enviar mensagens para seus aliados sem que elas fossem descobertas se caíssem em mãos inimigas. Assim, ele teria criado um mecanismo onde um número indicava o deslocamente das letras de uma mensagem conforme o alfabeto. Exemplo, digamos que a “chave” desta semana seja 5 (o termo chave é usado pois é como se a mensagem original estivesse guardada em um cofre). Assim, todas as letras de uma mensagem estariam deslocadas 5 casas para direita, tornando a carta desfigurada para leitores desavisados, mas bastante reverter o processo com o número correto. Era um sistema bem simples mas ao mesmo tempo bem inovador para a época e funcionou durante um tempo.
Tirando a história de lado, a criptografia reversível pode ser dividida em duas subcategorias, de acordo com seu número de chaves. Quando temos apenas uma chave para criptografar e descriptografar, como no caso das Cifras de César, temos a Criptografia Simétrica ou os chamados algoritmos de Chave Simétrica. Já os algoritmos que usam mais de uma chave, sendo as mesmas diferentes, são chamados de Assimétricos.
#2.a – Criptografia de Chave Simétrica
Algoritmos de chave simétrica são algoritmos para criptografia que usam a mesma chave criptográfica para encriptação de texto puro e decriptação de texto cifrado. A chave, na prática, representa um segredo compartilhado entre duas ou mais partes que pode ser usado para manter uma ligação de informação privada. A Cifra de César que citei antes é um bom exemplo.
Embora quando a gente fale “chave” você possa pensar em uma senha em texto, as chaves criptográficas são longas cadeias de bits, já que todo o processo de cifrar e decifrar se dá bit a bit com operações matemáticas complexas da chave sobre os bits do texto. Aliás, a área de criptografia e todos seus algoritmos surgiu e evolui através do trabalho dos matemáticos, sendo os programadores responsáveis “apenas” pela sua implementação prática em código, existindo implementações dos algoritmos de criptografia mais famosos em todas linguagens de programação comerciais. Mas voltando ao assunto da chave, quando a vemos representada em texto é exatamente isso: apenas uma representação, sendo que o que importa geralmente são os bits por trás daquele texto.
Assim, se você tem uma chave “123” e quer cifrar um texto “olá mundo”, os bits da chave serão usados em uma fórmula matemática complexa sobre os bits do texto e o resultado será a mensagem cifrada, exemplo, “2j4l8v48”. Se o algoritmo for simétrico, com a mesma chave “123” deve ser possível transformar “2j4l8v48” em “olá mundo” novamente.
Mas Luiz, se a chave for de tamanho diferente da mensagem, o que acontece?
Isso é bem comum de acontecer, já que raramente uma chave será tão grande quanto um texto pode ser. Independente do tamanho do texto, um algoritmo simétrico vai ter duas abordagens possíveis para garantir que todo o conteúdo será cifrado de maneira segura: ou ele vai cifrar em blocos ou em fluxo.
#2.b – Criptografia Simétrica em Bloco
Os algoritmos de criptografia de chave simétrica em bloco são os mais comuns. Basicamente eles pegam blocos do texto a ser cifrado que possuam o mesmo comprimento (em bits) da chave que será usada e aplicam a fórmula de cifragem com a chave, um bloco de cada vez. Caso algum bloco, geralmente o último, fique de tamanho menor, adiciona-se “paddings” como zeros, por exemplo.
O algoritmo de criptografia simétrica em bloco mais utilizado atualmente é o AES (Advanced Encryptio Standard) com chaves de 256-bit (recomendação atual), que é o padrão federal dos EUA desde 2002. Abaixo tem um exemplo de uso do AES em funções de cifragem e decifragem na linguagem JavaScript.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
const aes = require('aes-js'); const key = aes.utils.utf8.toBytes(process.env.AES_KEY); if (key.length !== 32) throw new Error('Invalid key size for AES. Must be 256-bit / 32 bytes.'); function encrypt(text) { const bytesInfo = aes.utils.utf8.toBytes(text); const aesCtr = new aes.ModeOfOperation.ctr(key); const encryptedBytes = aesCtr.encrypt(bytesInfo); const encryptedHex = aes.utils.hex.fromBytes(encryptedBytes); return encryptedHex; } function decrypt(encryptedHex) { const encryptedBytes = aes.utils.hex.toBytes(encryptedHex); const aesCtr = new aes.ModeOfOperation.ctr(key); const decryptedBytes = aesCtr.decrypt(encryptedBytes); return aes.utils.utf8.fromBytes(decryptedBytes); } module.exports = { encrypt, decrypt } |
Esse tipo de criptografia é muito utilizado quando temos um conteúdo de tamanho conhecido que deve ser ocultado até que seja necessário sua descoberta novamente.
#2.c – Criptogtafia Simétrica de Fluxo
A principal diferença conceitual entre os algoritmos de bloco e os de fluxo é que não sabemos o tamanho da mensagem a ser cifrada e não podemos esperar os blocos se formarem, assim, conforme os bits vem chegando, vamos usando um gerador de bits para ir criptografando eles, um a um. Esse gerador de bits é inicializado com a chave de criptografia, assim seu resultado não pode ser previsto.
A imagem abaixo mostra um exemplo conceitual de cifragem (à esquerda) e decifragem (à direita).
Esse tipo de criptografia é muito utilizado por exemplo em sistemas de roteadores wifi, sinais de rádio e outros, onde o fluxo de bytes é constante e um dos algoritmos mais populares, embora não tão seguro, seja o RC4 que é usado em sistemas WEP (Wired Equivalent privacy). O mais recomendado no entanto é é o padrão WPA (Wifi Protected Access) com algoritmo TKIP, que muda as chaves automaticamente de tempos em tempos. Isso porque a fraqueza do RC4 está justamente em, após longos períodos de uso, os atacantes terem conteúdo criptografado suficiente para começar a prever seu padrão.
#2.d – Conclusões
Como vantagens dos algoritmos de chave simétrica temos a sua performance, que costuma ser muito boa, mas quando o assunto é “força” da criptografia, ela está diretamente ligada ao tamanho e segredo da sua chave: sistemas de chave simétrica são tanto ou mais seguros quanto o for (1) a própria chave e (2) o meio em que ela foi dada a conhecer a ambos interlocutores — é comum a chave estar guardada num local que se “pensa” ser seguro.
A maior desvantagem dos algoritmos de chave simétrica é justamente a exigência de uma única chave secreta compartilhada, com uma cópia em cada extremidade. As chaves estão sujeitas à descoberta potencial por um adversário criptográfico, por isso necessitam ser mudadas freqüentemente e mantidas seguras durante a distribuição e no serviço. Essa exigência de escolher, distribuir e armazenar chaves sem erro e sem perda, é conhecida como “gerenciamento de chave”.
Vazou a chave, já era!
Na próxima parte deste artigo falaremos da segunda família de algoritmos de criptografia reversível que são os de Chave Assimétrica, confira aqui!
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.