• Nenhum resultado encontrado

Algoritmos Baseados em Hashing (MD5, SHA-1)

9.3 Algoritmo SHA-

O algoritmo SHA-1 foi desenvolvido pelo NIST em 1993 (RFC3174, 1994). A entrada pode ser de comprimento arbitrário e deve ser completada para que o comprimento se torne múltiplo de 512 bits (como ocorre com o MD5).

A saída deste algoritmo é de 160 bits sendo que blocos de 512 bits são processados a cada passo (RFC3174, 1994). Este algoritmo possui uma menor probabilidade de colisão quando comparado com o algoritmo MD5, sendo que no algoritmo SHA-1 existe a probabilidade de ocorrer colisões após 280 aplicações, contra 264 aplicações do MD5 (MENEZES, 1997).

A estrutura do algoritmo SHA-1 é parecida com a estrutura do algoritmo MD5. O algoritmo SHA-1, a exemplo do algoritmo MD5, possui um buffer que é atualizado a cada operação e que será o resultado final do hash. Neste caso como a saída é de 160 bits o buffer é composto por cinco partes de 32 bits aqui chamados de (A, B, C, D e E). O algoritmo SHA-1 utiliza também um segundo buffer de cinco partes de 32 bits que aqui serão chamadas de H0, H1, H2, H3 e H4.

O buffer do algoritmo SHA-1 deve ser iniciado com os valores contidos na tabela 9.4. (os valores estão em hexadecimal).

Tabela 9.4 – Valores para preencher o buffer do SHA-1

H0 67 45 23 01 H1 EF CD AB 89 H2 98 BA DC FE H3 10 32 54 76 H4 C3 D2 E1 F0

164 No inicio de cada passo um bloco de entrada (X) de 512 bits é utilizado para criar um vetor W de 80 palavras de 32 bits. Inicialmente, o bloco de entrada X é dividido para formar as 16 primeiras palavras do vetor W (W0 a W15). As palavras de W16 até

W79 são formadas obedecendo: Wi = (Wi-3 XOR Wi-8 XOR Wi-14 XOR Wi-16) <<< 1;

onde a <<< b representa o deslocamento circular de a para esquerda b bits.

O algoritmo SHA-1 possui quatro funções e quatro constantes que são utilizadas de acordo com a iteração que estiver sendo processada; desta forma a tabela 9.5 apresenta as funções e constantes utilizadas e indica em quais iterações devem ser utilizadas.

Tabela 9.5 – Funções e Constantes utilizadas pelo SHA-1

Função Constante Iterações f(B,C,D) = (B AND C) OR ((NOT B) AND D) 5A827999 0 a 19 f(B,C,D) = B XOR C XOR D 6ED9EBA1 20 a 39 f(B,C,D) = (B AND C) OR (B AND D) OR (C AND D) 8F1BBCDC 40 a 59 f(B,C,D) = B XOR C XOR D CA62C1D6 60 a 79

Antes de executar as iterações necessárias para o processamento de um bloco com o algoritmo SHA-1, é realizada uma cópia dos valores contidos no buffer H0, H1, H2,

H3 e H4 para o buffer A, B, C, D e E.

O processamento de um bloco com o algoritmo SHA-1 consiste de 80 iterações (de i=0 até i=79) onde são processadas as seguintes operações:

TEMP = (A<<<5) + fi(B,C,D) + E + Wi + Ki;

E = D; D = C; C = (B<<<30); B = A; A = TEMP;

Após a execução do laço principal é realizado o somatório dos dois buffers como segue:

H0 = H0 + A; H1 = H1 + B; H2 = H2 + C; H3 = H3 + D; H4 = H4 + E

Após processar todos os blocos da mensagem o valor do hash estará armazenado no buffer H0, H1, H2, H3 e H4.

9.3.1 Implementação em C

Assim como o algoritmo MD5, o algoritmo SHA-1 foi implementado nas linguagens C e Java. Nesta seção serão destacados os principais aspectos relativos a implementação do algoritmo SHA-1 em C.

O algoritmo SHA-1, assim como o MD5, trabalha com blocos de 512 bits. Desta forma, também é necessário realizar o preenchimento quando o tamanho da mensagem não for multiplo de 512 bits. A estrutura do preenchimento utilizada pelo SHA-1 é praticamente a mesma que a utilizada pelo algoritmo MD5, no entanto, ao contrário do MD5, o algoritmo SHA-1 utiliza o formato big-endian (o bit mais significativo é armazenado no endereço de memória mais baixo). Com isto, deve-se observar que o tamanho em bits da mensagem, que é acrescentado no final do último bloco, esteja no formato big-endian.

165 Isto faz com que as funções utilizadas para controlar o processamento da mensagem e acrescentar o preenchimento sejam praticamente as mesmas, com algumas pequenas alterações. Seguindo o exemplo do algoritmo MD5, são descritas três funções:

• sha1start() – responsável por inicializar o algoritmo SHA-1, definindo os valores iniciais utilizados pelo algoritmo.

• update(dados,numbytes) – acrescenta os dados em um buffer e quando o buffer estiver completo (512 bits) realiza a operação de hash neste bloco. O valor numbytes informa quantos bytes de dados devem ser considerados. • doFinal() – realiza o padding e calcula o hash do último bloco.

Como descrito anteriormente, o algoritmo SHA-1 utiliza um buffer H0, H1, H2, H3 e

H4 que deve ser iniciado com os valores contidos na tabela 9.4. Com isto, a seguir é

apresentada a função sha1start() que realiza esta operação.

void sha1start(void) { H0 = 0x67452301; H1 = 0xEFCDAB89; H2 = 0x98BADCFE; H3 = 0x10325476; H4 = 0xC3D2E1F0; tamanho[0] = 0; tamanho[1] = 0; nc = 0; }

As funções update() e doFinal() são praticamente as mesas utilizadas pelo algoritmo MD5 com algumas pequenas alterações. Na função update(), onde existe a chamada para o algoritmo MD5 deve ser substituida por uma chamada ao algoritmo SHA-1. A alteração na função doFinal() está relacionada com o tratamento do formato com que o tamanho da mensagem em bits é acrescentado no final do bloco; esta alteração é uma alteração do vetor tamanho[] para o formato big-endian.

O algoritmo SHA-1 utiliza quatro funções e quatro constantes que são definidas a seguir. #define f0(B,C,D) ((B&C)|((~B)&D)) #define f1(B,C,D) (B^C^D) #define f2(B,C,D) ((B&C)|(B&D)|(C&D)) #define f3(B,C,D) (B^C^D) #define K0 0x5A827999 #define K1 0x6ED9EBA1 #define K2 0x8F1BBCDC #define K3 0xCA62C1D6

Outra função importante utilizada pelo algoritmo SHA-1 é um deslocamento circular para a esquerda em n bits. A função é definida a seguir.

166 A função principal do algoritmo SHA-1 para o cálculo do hash de um bloco é apresentada a seguir. void sha1(void) { int i; convert(W); for(i=16;i<80;i++) W[i]= S((W[i-3]^W[i-8]^W[i-14]^W[i-16]),1); A=H0; B=H1; C=H2; D=H3; E=H4; for (i=0;i<20;i++) {

TEMP = (unsigned int)(S(A,5))+f0(B,C,D)+E+W[i]+K0; E=D;D=C;C=S(B,30);B=A;A=TEMP;

}

for (i=20;i<40;i++) {

TEMP = (unsigned int)(S(A,5))+f1(B,C,D)+E+W[i]+K1; E=D;D=C;C=S(B,30);B=A;A=TEMP;

}

for (i=40;i<60;i++) {

TEMP = (unsigned int)(S(A,5))+f2(B,C,D)+E+W[i]+K2; E=D;D=C;C=S(B,30);B=A;A=TEMP;

}

for (i=60;i<80;i++) {

TEMP = (unsigned int)(S(A,5))+f3(B,C,D)+E+W[i]+K3; E=D;D=C;C=S(B,30);B=A;A=TEMP;

}

H0+=A;H1+=B;H2+=C;H3+=D;H4+=E; }

Importante destacar que a função convert(W) que é utilizada para converter os dados contidos no buffer para o formato utilizado pelo SHA-1, que é de 16 partes de 32 bits deve considerar os dados no formato big-endian.

9.3.2 Desempenho em Software

De forma similar ao MD5, o algoritmo SHA-1 foi implementado usando-se da linguagem C e Java..

De maneira similar ao algoritmo MD5, foram realizadas implementações em C e em Java do algoritmo SHA-1. Os resultados são apresentados a seguir. Os testes apresentados consideram os mesmos arquivos utilizados nos testes com o MD5, sumarizando, estes arquivos são: Vídeo.MPG de 57,1 Mbytes; Música.MP3 de 6,43 Mbytes; e Documento.DOC de 346 Kbytes.

167 Para realizar os testes com o algoritmo SHA-1 foi utilizado o mesmo computador em que o algoritmo MD5 foi testado (AMD Duron 1,2Ghz, 128 Mbytes de memória RAM utilizando Windows XP).

Desta forma a figura 9.3 apresenta os dados referentes ao desempenho do algoritmo SHA-1 considerando as duas linguagens (C e Java). Através desta figura pode-se perceber mais uma vez que a implementação em Java é significativamente mais lenta que a implementação em C. Importante ressaltar mais uma vez que determinados arquivos processados pela implementação em C gastam tempo considerado insignificante. Os tempos apresentados na figura 9.3 estão em milisegundos (ms).

Figura 9.3 – Comparação das implementações em C e Java no SHA-1 (PINTO, 2004) Finalmente, a figura 9.4 apresenta uma comparação entre o desempenho dos algoritmos MD5 e SHA-1. Para realizar o teste foi considerado o maior arquivo do conjunto de testes (video.mpg com 51,7Mbytes) e a implementação em linguagem C utilizando sempre o mesmo computador. Pode-se perceber que o algoritmo MD5 é significativamente mais rápido que o algoritmo SHA-1.

Isto acontece por duas razões:

(i) o algoritmo SHA-1 foi desenvolvido de forma a evitar a probabilidade de colisão, sendo desta forma mais seguro que o algoritmo MD5 e,

(ii) O MD5 produz uma saída de 128 bits enquanto que no SHA-1 é de 160 bits, o que gera um tempo maior de processamento.

Desta forma, pode-se dizer que o algoritmo SHA-1 possui um desempenho inferior em termos de processamento, mas provê uma maior segurança.

168 Figura 9.4 – Comparação de desempenho: MD5 x SHA-1 (PINTO, 2004)

169

Parte III

Documentos relacionados