Assinando arquivos

A forma mais prática e segura de saber se um arquivo foi alterado ou não é através de uma assinatura eletrônica. No Linux você pode fazer isso via linha de comandos rapidamente para hash md5, sha1, sha256, sha512 entre outros.Em uma explicação bem rudimentar e simplista, assinar um arquivo consiste em realizar um cálculo matemático altamente complexo sobre o seu conteúdo e que resulta em um “número gigante”, chamado de “hash”.

Colisões

Tal como a nossa assinatura em documentos de papel, em tese, ela nunca haverá dois arquivos com a mesma assinatura ainda que eles sejam minimamente alterados. Na prática não é possível assegurar que este hash seja de fato único, ainda mais com a quantidade de arquivos digitais crescendo absurdamente.

Quando ocorre de dois arquivos diferentes possuírem a mesma assinatura dizemos que houve uma “colisão de hashs”, o que se faz então para evitar este problema é com o passar dos anos ir abandonando os algoritmos antigos e adotar novos cada vez mais complexos, você pode saber mais sobre isso na Wikipédia ou neste interessante artigo do Peter Selinger [1].

Algoritmos

Não vou me alongar em teorias pois este é um assunto que nos torna velhos, barburdos, aumenta o grau do óculos e nos promove a usuários de remédio tarja preta então indo diretamente para prática é importante saber que há alguns algoritmos  prontos e obviamente ferramentas de uso geral disponíveis por ai que atendem perfeitamente bem as necessidade de uma rotina.

Dentre os algoritmos mais comuns estão os da “família” “MD” (MD4, MD5) e “SHA” (SHA1, SHA256, SHA512 etc) e embora eu os tenha listado em uma ordem do menor (maior probabilidade de colisão) para o maior (menor probabilidade de colisão), há outros algoritmos entre estes e de outras famílias também.

Mas pra que ser isso?

A ideia principal da assinatura de arquivos é assegurar que o conteúdo do arquivo que você está vendo é exatamente aquele que a pessoa quem criou tinha a intenção de que você encontrasse.

Por exemplo eu posso manter uma assinatura dos meus arquivos mais críticos do sistema e se em algum momento alguém alterar intencionalmente qualquer um deles, através das assinaturas eu conseguiria saber qual arquivo foi violado.

Se você já baixou arquivos ISO com imagens de CD e DVD Linux já deve ter visto que nas páginas de download geralmente estão disponíveis os arquivos MD5SUM, SHA1SUM, SHA256SUM etc.

Eles estão lá justamente para que você tenha como confirmar se o arquivo ISO que você baixou é exatamente aquele que a comunidade que os mantém disponibilizaram.

Em um outro exemplo, você poderia assinar seus arquivos dentro “/etc” e diariamente verificar estas assinaturas. Caso em algum momento você encontre um arquivo com assinatura diferente então ele pode ter sido violado (invasão, alteração indevida …). Dependendo do caso você precisará de um backup para restaurar o arquivo original, mas esse assunto está fora do contexto no momento.

Em um terceiro e ultimo exemplo você pode usar os hashs para saber se há arquivos duplicados dentro dos seus sistemas. Neste caso você, forma grosseira, você calcularia os hashs de todos os seus arquivos e depois conferiria se há algum repetido. Considerando que não houve colisão, se você encontrar dois arquivos com o mesmo hash, ainda que em locais e nomes diferentes há uma grande chance de que estes arquivos estejam duplicados.

Na prática

No Linux para assinar um arquivo com qualquer destes algoritmos basta invocar o comando referente passando o arquivo desejado como nos exemplos abaixo onde retorno a assinatura de um mesmo arquivo usando vários algoritmos.

$ md5sum iptables.rules
bb958a5f1a2fc013927c8c3fa38334d2  iptables.rules
$ sha1sum iptables.rules
ea4fc1c6345488b9c7b0d8d691ac1ff08f831995  iptables.rules
$ sha256sum iptables.rules
66177294b440546ef391eda8a0f2cdc2c0f1984c3e232001265dd15a9570205d  iptables.rules
$ sha384sum iptables.rules
c76d4a98d55828c7e63dd00d4cdd4f68a4c485449985a879c542f36e976193563c003c739897b7a7449c6a752e08e310  iptables.rules
$ sha512sum iptables.rules
0b0feb15a309e5c9ed1aec48acd211acf0c0312e7c2671ab3e8b0f6ebd520df22e42cd3edfd004c2ae45fb5a10a778a9a42e60dacebbdae304f6314aec2f8aef  iptables.rules

Veja que o arquivo é o mesmo, no entanto cada algoritmo resulta em uma assinatura diferente e maior, diminuindo a probabilidade de ocorrer uma colisão.

Praticamente todas as linguagens de programação modernas possuem alguma biblioteca com funções para calcular hashs, então digamos que sua equipe de desenvolvimento precisa fazer uma aplicação que gera um arquivo critico e que será enviado pela rede para outro local.

A aplicação poderia calcular a assinatura do arquivo antes de enviar e do outro lado quando o arquivo chegar validar se a assinatura do arquivo que chegou é exatamente a mesma do que foi enviado.

Exemplo em Python

A baixo segue um exemplo em Python de como calcular a assinatura md5 e sha1 do mesmo arquivo dado como exemplo anteriormente.

# coding: utf-8
import hashlib
arq = open ("iptables.rules",'r')
conteudo = arq.read()
arq.close()
ass = hashlib.md5(conteudo)
ass2 = hashlib.sha1(conteudo)
print "MD5 : %s"%ass.hexdigest()
print "SHA1: %s"%ass2.hexdigest()

Executar este script na minha máquina resultará na seguinte saída:

python hashteste.py
MD5 : bb958a5f1a2fc013927c8c3fa38334d2
SHA1: ea4fc1c6345488b9c7b0d8d691ac1ff08f831995

Como estou calculando os hashs MD5 e SHA1 do mesmo arquivo do exemplo anterior, os valores são os mesmos, como era de se esperar.

O que lembrar?

Este assunto é bastante técnico e por isso este texto pode ser apenas um esboço para futuros textos mais completos ou que possam partir deste ponto, mas no momento, o que importa lembrar é que se você precisa assegurar que um arquivo recebido é exatamente aquele que foi enviado, use uma assinatura.

Referências

[1] Selinger, Peter. MD5 Collision Demo. Department of Mathematics and Statistics / Dalhousie University . http://www.mscs.dal.ca/~selinger/md5collision/ em 10-04-2017.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *