Você está na página 1de 8

O que é Criptografia?

Criptografia é, de maneira simples, “escrever em códigos“. Não vou dedicar linhas à uma
abordagem histórica da criptografia. O que interessa é que a ciência da criptografia, a
criptologia, é muito antiga. No começo, era bem simples. Coisa que com papel e caneta você
faz. Hoje em dia, é muito mais complexa, códigos que se você colocar todos os computadores
do mundo pra tentar quebrar vai precisar de mais tempo que a idade estimada do universo pra
ter sucesso.

Ih, já comecei a complicar. Códigos, quebrar? Ok, vou tentar ir com mais calma.

Em geral, a criptografia é o processo de transformar um texto compreensível (que


chamaremos de mensagem) em um texto codificado (que chamaremos de código), usando
uma fórmula matemática (que chamaremos de cifra). “Mas espera aí, fórmula matemática?“.
Sim! Toda informação num computador, seja o que for, está armazenada na forma de
números. Uma figura, um texto, etc. Tudo isso são números. Aplica-se uma fórmula sobre um
número, ele vira outro número. De maneira simplificada, isso é a cifragem, ou seja: Você pega
uma mensagem (número), aplica uma cifra (fórmula) e obtém um código (outro número).

Agora, você lembra que lá na escola você aprendeu uma coisa chamada função inversa?
Aquela, que se aplicada sobre a resposta obtida na função, retorna o número original? Por
exemplo, a função inversa de:

f(x) = x+1

g(x) = x-1

Simples, não? Quando fazemos isso, podemos dizer que estamos decifrando o código. Ou seja,
pegamos um código (o número obtido na cifragem), aplicamos uma cifra inversa (função
inversa) e obtemos nossa mensagem de volta. Você pode estar pensando: “Ok, mas este
exemplo foi ridiculo“. Sim, pra nós, hoje em dia, chamar isso de criptografia pode parecer
ridículo. Mas o Grande Júlio César fez uso de uma cifra muito parecida, a famosa Cifra de
César, que envolvia associar cada letra a um número e simplesmente fazer algo muito parecido
com o que acabamos de fazer: somar 13 para cifrar, e tirar 13 para decifrar.

Na verdade está envolvida aí uma operação modular, ou seja, imagine os números como indo de 1 a 26
(26 letras do alfabeto) apenas, se chegar a 27 você na verdade volta a 1, e vice-versa, se chegar a 0,
volta pro 26. Pra facilitar, coloque os números em um círculo. Note que a obtenção do módulo,
matematicamente falando, nada mais é que obter o resto da divisão (28 mod(26) = 2, pois 27 dividido por
26, dá 1 e sobra 2). Pode parecer difícil, mas você certamente já viu isso antes, mas talvez só não
percebeu: 15 horas no seu relógio digital, é indicado como 3 horas no seu relógio de ponteiro que
representa as 24 horas do dia em módulo 12.

Claro que hoje em dia as coisas não são mais tão simples. As cifras evoluiram muito em complexidade,
usando alguns artifícios da matemática que não vou comentar aqui por não atender o objetivo dos meus
posts.

Uma última coisa importante: o número 13 da cifra de César, pode ser considerado como um exemplo
simples de uma coisa importante de qualquer cifra moderna. O número poderia ser qualquer um, de 1 a
25, certo? Ou seja, e você usar 12 para cifrar a mesma mensagem, o código obtido será diferente. Este
valor que podemos escolher, e que afeta o resultado obtido, é o que chamamos de chave. No caso de
César, se não soubermos a chave, precisamos tentar só as 25 possíveis, o que você pode fazer com lápis
e papel em poucos minutos. E com um computador, nem se fala. Esse negócio de tentar todas as chaves
possíveis é um dos jeitos mais conhecidos de quebrar um código, e recebe o nome de ataque por força
bruta (faz sentido, né?). Uma boa cifra moderna precisa mais do que a idade estimada do universo pra ser
quebrada assim.

No último post desta série comentei alguns aspectos básicos sobre criptografia. Falei de maneira mais
simples possível o que é criptografia e como ela é realizada. Terminei falando sobre a questão da chave, e
a sua importância.

Não sei se você parou pra pensar, mas a chave é um problema. Se você quer cifrar uma mensagem,
passar ela para outra pessoa, e quer que ela possa decifrar a mensagem, você precisa passar a chave pra
essa pessoa. E se você está cifrando o texto, quer dizer que você quer que só aquela pessoa possa ler a
mensagem, mais ninguém. A questão óbvia é: como vou enviar a chave de maneira segura? Mandar ela
junto com a mensagem não dá, qualquer pessoa que tiver acesso no meio do caminho vai poder ler a
mensagem, pois tem a chave e a mensagem. Talvez então telefonar e falar a chave? Oras, se o telefone é
seguro, por que não fala a mensagem pelo telefone de uma vez?
A mesma coisa vale pra todo outro meio que você puder imaginar. Como é possível resolver este dilema?

A criptografia simétrica, que é essa aí onde você combina uma única chave que é conhecida pelas duas
pessoas, é sim muito utilizada. Mas antes de começar a falar como se faz, afinal, pra combinar essas
chaves de maneira segura, vou falar sobre outro tipo de criptografia. A criptografia assimétrica!!!

Não seria bom se, quando eu quero cifrar um texto pra você, você pudesse me falar sua chave
publicamente, por exemplo colocar ela no seu site? A criptografia assimétrica permite isso. A
ideia básica é a seguinte: através de uma série de artifícios matemáticos (envolvendo por
exemplo números primos), é possível fazer criptografia com duas chaves. Uma, você guarda
pra você, e chama de chave privada. A outra, você fala pra todo mundo, e chama de chave
pública. Existem métodos de gerar essas chaves, de forma que vão acontecer três coisas muito
interessantes:

* Se você cifrar algo usando a chave privada, só a chave pública pode decifrar o código gerado.
Ou seja, se você usar sua chave privada para cifrar uma mensagem, todo mundo vai poder
decifrá-la! Isso pode parecer inútil pra você neste momento, mas em outro artigo, vou mostrar
a utilidade disso.
* Se você cifrar algo usando a chave pública, só a chave privada pode decifrar o código gerado. Agora
sim! Se você percebeu, todos tem acesso à sua chave pública, não apenas você! Ou seja, todos podem
cifrar mensagens que só você pode abrir!
* E, como não poderia deixar de ser, é impossível descobrir qual é a chave privada tendo apenas acesso à
chave pública. Como não pretendo entrar em detalhes, apenas aceite que, usando bons métodos de
geração de chaves, isso é verdade.
Ou seja, basta cada pessoa gerar um par de chaves, contar a sua chave pública pra todo mundo, e nossos
problemas acabaram! É claro, existem várias coisas que devem ser observadas, e gerar estas chaves não
é algo tão simples assim (é simples suficiente pra qualquer computador caseiro fazer em poucos
segundos). Mas é possível e é assim que funcionam muitos dos sistemas de criptografia modernos. A
figura abaixo ilustra o processo de cifragem e decifragem com criptografia assimétrica:

Agora você pode estar perguntando: por que, então, ainda se usa criptografia simétrica? A
resposta é simples: ela é muito mais rápida. Se você precisa cifrar milhões de dados, não vai
querer usar a criptografia assimétrica. Mas que tal usar a criptografia assimétrica pra combinar
uma chave, e depois usar de novo criptografia simétrica ? Se a criptografia assimétrica é
“cara”, use ela só pro que interessa, ou seja, cifrar com a chave pública da pessoa com quem
você quer se comunicar uma quantidade pequena de informações: uma chave simétrica.
Depois que ambos conhecem a chave simétrica, pronto, use ela para trocar dados sigilosos. É
baseado nessa ideia que funciona inclusive o sistema de “sites seguros”, aqueles com https e
“cadeado”, por exemplo os sites de bancos virtuais.

No próximo post, agora que temos um pouco de noção dos dois principais modos de
criptografia, farei uma abordagem um pouco mais prática, mostrando exemplos reais de onde
você utiliza criptografia no seu dia-a-dia.

Assinatura Digital

Dentro da criptografia, existem algumas funções além da cifragem e decifragem, sobre


as quais já comentei nos outros posts. Uma delas, muito importante, é a chamada função
hash, ou, em bom português, resumo.

Uma função hash é uma função que pega uma mensagem de qualquer tamanho, e
converte ela num número aparentemente aleatório, de tamanho fixo. A mesma
mensagem sempre resultará no mesmo hash, não importa onde e quando você utilizar a
função (desde que, é claro, seja a mesma função hash. Existem várias funções hash,
algumas das mais utilizadas hoje são a MD5, a SHA-1 e a SHA-256).

É claro que, se o número é de tamanho fixo, se a mensagem for maior que o número,
necessariamente dados vão ser “jogados fora” na hora de calcular o hash. Ou seja, não
tem como você obter a mensagem original a partir de um hash. Por isso, muita gente usa
o hash pra armazenar senhas de websites no banco de dados, por exemplo. “Como, se
não dá pra obter a senha de volta?”. Elementar, caro Holmes: O que se faz é armazenar
o hash da senha. Quando você informa sua senha no login, o site gera o hash de novo, e
compara os hashes, não as senhas. Se forem iguais, a senha deve ser igual. Mas se
algum cracker invadir o servidor e roubar o banco de dados, ele vai ver apenas hashes, e
não senhas. Isso tem um pequeno problema, mas vou deixar pra comentar isso mais no
final.
Uma aplicação muito mais interessante (na minha opinião) do hash é a assinatura digital. Quando você
assina um documento, na vida real, com caneta e sua mão, você garante a autenticidade daquele
documento, certo? Ou seja, se a assinatura é sua, você está ciente do conteúdo do documento. Mas falta
uma coisa: integridade. Quem garante que nada foi adicionado ao documento depois que você assinou
ele? Se você assina um cheque em branco, qualquer coisa que for preenchida nele depois será paga, não
importa se é o que você queria que fosse pago ou muito mais. Para contratos, o que se faz é autenticar e
registrar o documento, em cartório, e emitir várias vias do mesmo documento. Se alguém aduleterar o
documento, o cartório pode provar qual é o original.

Na assinatura digital, tanto a autenticidade quanto a integridade são garantidas. Vamos ver como
funciona:

Você tem uma mensagem, que quer assinar, no seu computador. Você primeiro gera um hash (resumo)
dessa mensagem. Depois cifra esse hash com sua chave privada (lembra da criptografia assimétrica?. Aí
você anexa este hash cifrado na sua mensagem, e manda ela ao destinatário.

O que vai acontecer? Como vimos na parte 2, quando alguém cifra algo usando a chave privada, significa
que todo mundo pode decifrar essa mensagem. Não tinha mostrado nenhuma utilidade pra isso ainda,
mas agora você vai entender: O destinatário, recebendo a mensagem e o hash cifrado, pode decifrar o
hash com a sua chave pública. Assim, ele sabe que foi você que assinou, e passa a ter certeza da
autenticidade, pois você é a única pessoa no mundo que conhece a chave privada, então só você poderia
ter cifrado aquele hash. Ele vai obter um hash, e ele mesmo vai gerar um novo hash a partir da
mensagem que recebeu. Ele compara o hash que você mandou cifrado, com o hash que ele acabou de
gerar, e vê se são iguais. Desta forma, agora além da autenticidade, ele pode ter certeza da integridade
da mensagem. Simples não? Aí vai uma figura ilustrando essa idéia (a chave vermelha é a chave privada
do remetente, a verde é a pública):

Esta imagem foi redimensionada. Clique nesta barra para ver a imagem completa. A imagem original é de tamanho 837x322.

Colisão de Hash

Uma das questões importantes dos hashes é a chamada colisão de hashes. Se você parar pra pensar, o
fato do hash ter tamanho fixo, mas o número de mensagens ser infinito, significa que necessariamente
existem diferentes mensagens que tem o mesmo hash. Ou seja, levando para fins práticos, é possível que
duas senhas diferentes tenham o mesmo hash, e por isso, para acessar a conta do Fulano você possa usar
a senha do Sicrano. Ou pior. Você pode assinar um documento digital que é apenas um email para um
amigo. Mas o hash deste email é justamente o mesmo hash de um texto de contrato que passa todo seu
dinheiro para uma determinada pessoa. E na prática, isso significa que se eu colocar a assinatura digital
do email anexa ao contrato, todo mundo vai achar que a assinatura foi mesmo feita sobre o contrato. Eu,
heim! Esta técnica, de tentar obter mensagens diferentes que tem o mesmo hash, é o que é chamado de
colisão de hash. A figura abaixo demonstra este ataque:

Esta imagem foi redimensionada. Clique nesta barra para ver a imagem completa. A imagem original é de tamanho 861x362.

Mas calma, não entre em pânico. Pensando nisso, mensagens de hash são virtualmente aleatórias. Um
bom hash é feito de tal forma que seu comprtamento é imprevisível, ou seja, você não deve conseguir
montar uma mensagem querendo chegar num determinado hash. E mais do que isso, um bom hash é
aquele que, modificando 1 bit na mensagem (lembre-se que o computador, tudo são números, e números
representados na forma de bits 0 e 1), metade dos bits do hash mudam. Ou seja, é praticamente
impossível, com boas funções hash, obter uma colisão que tenha alguma utilidade prática.

O ataque é ainda eficiente para descobrir senhas, já que nesse caso não interessa descobrir a senha de
verdade, e sim apenas uma senha que gere o mesmo hash. Não importa se a senha que você vai achar é
a senha de verdade, ou seja, a data de nascimento do usuário, ou se for $CNSDLKU@$*() mas tenha o
mesmo hash e portanto permite o acesso ao site do mesmo jeito. É por isso que cada vez mais as funções
de hash simples estão sendo substituídas por funções de hash com um negócio chamado salt, que faz
com que o hash seja diferente com salts diferentes e isso dificulte bastante o processo de colisão.

Mas para o caso de assinaturas digitais, se uma colisão for encontrada, é muito provável que somente
uma das mensagens tenha sentido. As demais provavelmente não passarão de um amontoado de
caracteres aleatórios, sem sentido algum. E mesmo esse amontoado de caracteres é difícil de encontrar.
Por isso, neste caso, não há motivo para preocupação, desde que você esteja utilizando sempre boas e
modernas funções hash.

Claro, você deve considerar que toda função hash um dia será considerada fraca. Por exemplo o MD5, que
por muito tempo utilizado, hoje já tem exemplos de colisões úteis. Ou seja, uma assinatura tem prazo de
validade, e é preciso um jeito de manter a validade dessa assinatura por muito tempo - de preferência,
pra sempre. A boa notícia é que existe sim um jeito de fazer isso, e se chama carimbo de tempo, que é
uma técnica que permite ter certeza sobre quando uma assinatura foi feita - mesmo que no futuro a
função de hash tenha sido quebrada, você saberá que quando a assinatura foi feita ela ainda era segura,
e por isso pode confiar na assinatura. Mas aí já estaremos indo longe demais para este artigo.
O MD5 (Message-Digest algorithm 5) é um algoritmo de hash de 128 bits
unidirecional desenvolvido pela RSA Data Security, Inc., descrito na RFC 1321, e muito
utilizado por softwares com protocolo ponto-a-ponto (P2P, ou Peer-to-Peer, em inglês),
verificação de integridade e logins.

Foi desenvolvido em 1991 por Ronald Rivest para suceder ao MD4 que tinha alguns
problemas de segurança. Por ser um algoritmo unidirecional, uma hash md5 não pode ser
transformada novamente no texto que lhe deu origem. O método de verificação é, então, feito
pela comparação das duas hash (uma da base de dados, e a outra da tentativa de login). O
MD5 tambem é usado pera verificar a integridade de um ficheiro através, por exemplo, do
programa md5sum, que cria a hash de um ficheiro. Isto pode-se tornar muito útil para
downloads de ficheiros grandes, para programas P2P que constroem o ficheiro através de
pedaços e estão sujeitos à corrupção dos mesmos. Como autenticação de login é utilizada em
vários sistemas operacionais unix e em muitos sites com autentificação.

Segue-se um pseudocódigo para o algoritmo MD5

Citação:

//Definir r como o seguinte


var int[64] r, k
r[ 0..15] := {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22}
r[16..31] := {5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20}
r[32..47] := {4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23}
r[48..63] := {6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}

//Utilizar a parte inteira dos senos de inteiros como constantes:


for i from 0 to 63
k[i] := floor(abs(sin(i + 1)) × 2^32)

//Iniciar as variáveis:
var int h0 := 0x67452301
var int h1 := 0xEFCDAB89
var int h2 := 0x98BADCFE
var int h3 := 0x10325476

//Pre-processamento:
append "1" bit to message
append "0" bits until message length in bits ≡ 448 (mod 512)
append bit length of message as 64-bit little-endian integer to message

//Processar a mensagem em pedaços sucessivos de 512-bits:


for each 512-bit chunk of message
break chunk into sixteen 32-bit little-endian words w(i), 0 ≤ i ≤ 15

//Inicializar o valor do hash para este pedaço:


var int a := h0
var int b := h1
var int c := h2
var int d := h3

//Loop principal:
for i from 0 to 63
if 0 ≤ i ≤ 15 then
f := (b and c) or ((not b) and d)
g := i
else if 16 ≤ i ≤ 31
f := (d and b) or ((not d) and c)
g := (5×i + 1) mod 16
else if 32 ≤ i ≤ 47
f := b xor c xor d
g := (3×i + 5) mod 16
else if 48 ≤ i ≤ 63
f := c xor (b or (not d))
g := (7×i) mod 16

temp := d
d := c
c := b
b := ((a + f + k[i] + w(g)) leftrotate r[i]) + b
a := temp

//Adicionar este pedaço do hash ao resultado:


h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d

var int digest := h0 append h1 append h2 append h3 //(expressed as little-endian)


Nota: Ao invés da formulação do RFC 1321 acima exibida, considera-se mais eficiente a
seguinte implementação:

Citação:

(0 ≤ i ≤ 15): f := d xor (b and (c xor d))


(16 ≤ i ≤ 31): f := c xor (d and (b xor c))
Hashes MD5

Os hashes MD5 de 128-bit (16-byte) são normalmente representados por uma sequência de
32 caracteres hexadecimais. O seguinte mostra uma string ASCII com 43-bytes e o hash
correspondente:

Citação:

MD5("The quick brown fox jumps over the lazy dog")


= 9e107d9d372bb6826bd81d3542a419d6
Mesmo uma pequena alteração na mensagem vai criar um hash completamente diferente, ex.
ao mudar d para c:

Citação:

MD5("The quick brown fox jumps over the lazy cog")


= 1055d3e698d289f2af8663725127bd4b
O hash de uma string vazia é:

Citação:

MD5("")
= d41d8cd98f00b204e9800998ecf8427e

MD5 craking online:

http://www.gdataonline.com/seekhash.php
http://www.hashchecker.com/index.php?_sls=search_hash
http://www.milw0rm.com/md5/
http://www.mmkey.com/md5/
http://www.rainbowcrack-online.com/
http://www.securitydb.org/cracker/
http://www.securitystats.com/tools/hashcrack.php
http://schwett.com/md5/
http://www.und0it.com/
http://www.xmd5.org/index_en.htm
http://linardy.com/md5.php
http://www.gdataonline.com/seekhash.php
http://www.md5-db.com/
https://www.w4ck1ng.com/cracker/
http://search.cpan.org/~blwood/Digest-MD5-Reverse-1.3/
http://www.hashchecker.com/index.php?_sls=search_hash
http://www.milw0rm.com/md5/
http://www.mmkey.com/md5/
http://www.rainbowcrack-online.com/
http://www.securitydb.org/cracker/
http://www.securitystats.com/tools/hashcrack.php
http://schwett.com/md5/
http://www.und0it.com/
http://www.md5.org.cn/index_en.htm
http://www.xmd5.org/index_en.htm
http://www.tmto.org
http://md5.rednoize.com/
http://nz.md5.crysm.net/
http://us.md5.crysm.net/
http://gdataonline.com/seekhash.php
http://passcracking.ru/
http://shm.pl/md5/
http://www.neeao.com/md5/
http://md5.benramsey.com/
http://www.md5decrypt.com/
http://md5.khrone.pl/
http://www.csthis.com/md5/index.php
http://www.md5decrypter.com/
http://www.md5encryption.com/
http://www.md5database.net/
http://md5.xpzone.de/
http://www.hashreverse.com/
http://alimamed.pp.ru/md5/
http://md5crack.it-helpnet.de/index.php?op=add
http://shm.hard-core.pl/md5/
http://rainbowcrack.com/
http://passwordsecuritycenter.com/in...;products_id=7
http://ice.breaker.free.fr/
http://www.md5this.com/
http://hackerscity.free.fr/
http://md5.allfact.info/
http://bokehman.com/cracker/
http://www.tydal.nu/article/md5-crack/
http://passcracking.com/
http://ivdb.org/search/md5/
http://md5.netsons.org/
http://md5.c.la/
http://www.md5-db.com/index.php
http://md5.idiobase.de/
http://md5search.deerme.org/
http://sha1search.com/