Criptografia em AdvPL – Parte 02

Introdução

No primeiro post da série sobre criptografia e hash (Criptografia em AdvPL – Parte 01), vimos uma breve introdução ao assunto, a lista de funções disponíveis no AdvPL para trabalhar com isso, e um exemplo de uso dos hashes MD5 e SHA*. Agora, vamos ver o hash com mais detalhes sobre cada um deles, e o que cada função permite fazer.

Vimos até agora superficialmente os hashes MD5 e SHA, mas existem vários outros algoritmos para fins específicos, como o RIPE Message Digest 160 Bits (RIPEMD160), que é considerado um hash mais “fraco”, utilizado em projetos onde o nível de segurança é aceitável. Vamos começar pelo MD5 e logo em seguida pelo SHA1.

MD5 message-digest algorithm

Criado por Ronald Rivest em 1991 para substituir uma função anterior de hash (MD4), cuja especificação foi publicada em 1992 na RFC 1321. Para os mais curiosos, veja nesse link o fonte em C da implementação do algoritmo MD5, e demais links de referência no final do post.

Segurança do HASH MD5

Embora o hash gerado tenha 128 bits — o que pode gerar 2^128 combinações distintas (aproximadamente 3,40e+38 combinações possíveis), a base do seu algoritmo hoje é considerada “fraca”, pois foram descobertas formas de ataque que permitem em tempo computacional ridiculamente pequeno forçar uma colisão de hash alterando ou injetando informações nos dados originais usados para gerar o HASH.

Onde isso impacta ?

Em diversos mecanismos de segurança de arquivos e assinaturas digitais, um HASH pode ser usado para garantir a integridade do conteúdo. Por exemplo, em vários sites de download um programa oficial é fornecido diretamente em um link, e logo abaixo é fornecido um HASH MD5, SHA1 ou outro, referente ao conteúdo disponibilizado. Com isso, após fazer o download, você pode executar uma ferramenta do sistema operacional ou um utilitário que calcule novamente o HASH do arquivo baixado. Se o HASH for diferente, ou o arquivo está corrompido, ou pode ter sido adulterado.

Em assinaturas digitais e chaves de criptografia, é fundamental que a chave não seja alterada por ninguém, pois isso permitiria alterar atributos da chave ou injetar código malicioso em um programa. Usando um algoritmo de busca por colisão, eu posso pegar um arquivo qualquer, acrescentar conteúdo nele, e temperar uma parte desse conteúdo para fazer com que o HASH gerado desse novo conteúdo seja idêntico ao HASH gerado pelo conteúdo inicial.

Com isso um certificado digital pode ser “forjado” a partir de um certificado original, e enganar o mecanismo de autenticação do certificado — veremos mais para a frente como isso funciona — mas na prática, você pode acessar um website com SSL, onde o Browser vai achar que o certificado é válido e que você está em uma conexão segura. Golpes como criar um site falso de um banco e pegar seus dados bancários podem ser criados usando  um certificado digital falso que o Browse acredita ser autêntico e verificado, e fazer você realmente acreditar que está acessando o site verdadeiro do banco, ou o sistema operacional acreditar que está usando um software original e autenticado, fornecido pelo próprio fabricante 😛

Entre 2005 e 2008 foram feitas diversas descobertas sobre as vulnerabilidades de colisão de MD5 e SHA1, e em 2008 uma equipe de pesquisadores usou um cluster de PlayStations 3 para forjar um certificado autenticado pela RapidSSL, e a partir dele poder criar outros certificados. Desde então não foram mais emitidos certificados com validação de autenticidade baseadas em MD5. EM 2012 foi identificado um malware chamado Flame, que forjou um certificado digital da Microsoft, fazendo os usuários acreditarem que estavam executando um programa autêntico da mesma. Em 2013 a Microsoft anunciou o fim do suporte a certificados digitais que usam autenticação com o MD5. Também suscetível a ataques desta natureza, as autenticações usando SHA1 também estão sendo descontinuadas, a Microsoft anunciou em 2013 que não recomenda o uso de SHA1 para esta finalidade, e informou para as autoridades certificadoras que deixará de reconhecer certificados com este algoritmo a partir de 2016.

Mesmo assim, MD5 e SHA1 ainda são bastante utilizados em outras finalidades, que não dependem de um nível de segurança maior, quando não compensa o esforço de tentar quebrá-lo.

SHA1 – Secure Hash Algorithm 1

Desenvolvido pela NSA (Agência de Segurança Nacional Americana), publicado na RFC 3174, o SHA1 retorna um código de 20 bytes (160 bits), correspondente a 40 caracteres em representação hexadecimal. Embora use um mecanismo diferente do MD5, o SHA1 também está sujeito a ataques de colisão, e não é recomendável seu uso em chaves criptográficas e certificados, e seu uso nestas aplicações vem sido descontinuado. Por outro lado, ele ainda é amplamente utilizado em outros fins, como determinar por exemplo se um arquivo está íntegro ou foi alterado, como por exemplo os softwares e plataformas de versionamento de fontes, como o GIT, por exemplo.

Funções AdvPL MD5() e MD5FILE()

Documentada no TDN nos links http://tdn.totvs.com/display/tec/MD5 e http://tdn.totvs.com/display/tec/MD5File, a função recebe uma string de tamanho variável, até o limite estabelecido para Strings em AdvPL, e retorna por default uma nova string de 32 caracteres contendo o código hash gerado, representado em hexadecimal. A string informada como parâmetro inclusive pode ser vazia, e pode conter bytes/caracteres de 0 a 255. Como cada byte informado na string de parâmetros é importante e significativo, uma string com um espaço em branco a mais na direita é diferente de uma sem este espaço, e cada uma vai gerar um hash diferente, por qualquer método utilizado. A função possui um segundo parâmetro, opcional, que quando informado com o número 1, faz a função retornar uma string de 16 bytes contendo a representação do HASH calculado.

Ela pode receber uma string originalmente de até 1 MB — tamanho máximo de uma variável “C” Caractere do AdvPL — mas este limite pode ser estendido usando a configuração MaxStringSize do TOTVS Application Server. Caso seja necessário gerar um HASH de um arquivo, você não precisa carregá-lo na memória para fazer isso, basta usar a função MD5File()

Um exemplo de uso da função já foi publicado anteriormente aqui no Blog, no uso do Banco de Dados para armazenamento de imagens em disco. Junto da imagem eu posso salvar o MD5 de seu conteúdo, e caso eu receba uma nova imagem para atualização, eu posso optar por não atualizá-la caso o MD5 gerado sobre o conteúdo da imagem seja o mesmo, veja links de referência no final do post.

No post sobre O que é CODEPAGE e ENCODING – Parte 04, eu menciono uma função do Framework AdvPL muito útil para determinar conteúdos binários dentro de strings, chama-se HexStrDump(). 

Função AdvPL SHA1()

Documentada na TDN no link http://tdn.totvs.com/display/tec/SHA1, ela recebe os mesmos parâmetros da MD5(), e aceita uma string de parâmetro com bytes de ASCII 0 a ASCII 255, retornando por default uma string com 40 caracteres em hexadecimal, correspondendo aos 20 bytes (126 Bits) do hash calculado.

Outras representações

Por padrão a maioria as funções do AdvPL retorna por default a representação do hash calculado em uma string hexadecimal, que ocupa duas vezes mais espaço do que efetivamente os bytes que compõe o hash. Porém, guardar um resultado de HASH em bytes em um campo de uma tabela em um Banco de Dados somente seria possível se fosse usado um campo do tipo “M” Memo, que aceita conteúdo binário. Porém, existem formas menores de representação que o hexadecimal. Por exemplo, podemos calcular um HASH SHA1 e parametrizar a função para retornar os 20 bytes correspondentes ao HASH, e depois codificar o resultado em BASE64 — assim o hash calculado poderia ser gravado em um campo de texto / caractere em apenas 24 caracteres, e não 40 caso ele fosse representado em hexadecimal, veja exemplo abaixo:

User Function SHaToB64()
Local cInfo := 'Hello AdvPL'
Local cSHA1 , cBase64

conout('String original')
conout(hexstrdump(cInfo))

cSha1 := SHA1(cInfo,1) // retorno de string em bytes 
conout('SHA1 em bytes')
conout(hexstrdump(cSha1))

cBase64 := Encode64(cSha1)
conout('Convertido para BASE64')
conout(hexstrdump(cBase64))

Return

// Resultado no console

String original
HexSTRDump  ( String 11 / Start 1 / Length 11 )
-------------------------------------------------------------------------------
48 65 6C 6C 6F 20 41 64 76 50 4C                 | Hello AdvPL
-------------------------------------------------------------------------------

SHA1 em bytes
HexSTRDump  ( String 20 / Start 1 / Length 20 )
-------------------------------------------------------------------------------
D7 E0 A3 66 D6 F2 62 C9 BC A0 F3 FE 89 0C 06 F9  | ╫αúf╓≥b╔╝á≤■ë__∙
B8 76 F6 ED                                      | ╕v÷φ
-------------------------------------------------------------------------------

Convertido para BASE64
HexSTRDump  ( String 28 / Start 1 / Length 28 )
-------------------------------------------------------------------------------
31 2B 43 6A 5A 74 62 79 59 73 6D 38 6F 50 50 2B  | 1+CjZtbyYsm8oPP+
69 51 77 47 2B 62 68 32 39 75 30 3D              | iQwG+bh29u0=
-------------------------------------------------------------------------------

No final das contas, precisamos utilizar os métodos de hashing e codificações exigidos por quem implementa uma determinada funcionalidade.

Conclusão

Ainda tem muito pela frente, mas eu acredito que a partir daqui cada nova etapa deve ficar mais clara.

Espero que estas informações lhes sejam úteis, e lhes desejo como sempre TERABYTES DE SUCESSO !!!

Referências

Copyrights

 *** MD5 message-digest algorithm
 *** Retrieved from https://people.csail.mit.edu/rivest/Md5.c
 
 **********************************************************************
 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
 **                                                                  **
 ** License to copy and use this software is granted provided that   **
 ** it is identified as the "RSA Data Security, Inc. MD5 Message     **
 ** Digest Algorithm" in all material mentioning or referencing this **
 ** software or this function.                                       **
 **                                                                  **
 ** License is also granted to make and use derivative works         **
 ** provided that such works are identified as "derived from the RSA **
 ** Data Security, Inc. MD5 Message Digest Algorithm" in all         **
 ** material mentioning or referencing the derived work.             **
 **                                                                  **
 ** RSA Data Security, Inc. makes no representations concerning      **
 ** either the merchantability of this software or the suitability   **
 ** of this software for any particular purpose.  It is provided "as **
 ** is" without express or implied warranty of any kind.             **
 **                                                                  **
 ** These notices must be retained in any copies of any part of this **
 ** documentation and/or software.                                   **
 **********************************************************************

SHA-1

RFC 3174           US Secure Hash Algorithm 1 (SHA1)      September 2001


Full Copyright Statement

   Copyright (C) The Internet Society (2001).  All Rights Reserved.

   This document and translations of it may be copied and furnished to
   others, and derivative works that comment on or otherwise explain it
   or assist in its implementation may be prepared, copied, published
   and distributed, in whole or in part, without restriction of any
   kind, provided that the above copyright notice and this paragraph are
   included on all such copies and derivative works.  However, this
   document itself may not be modified in any way, such as by removing
   the copyright notice or references to the Internet Society or other
   Internet organizations, except as needed for the purpose of
   developing Internet standards in which case the procedures for
   copyrights defined in the Internet Standards process must be
   followed, or as required to translate it into languages other than
   English.

   The limited permissions granted above are perpetual and will not be
   revoked by the Internet Society or its successors or assigns.

   This document and the information contained herein is provided on an
   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.