Função 'SHA1' da openssl gerando resumo errado [RESOLVIDO]

1. Função 'SHA1' da openssl gerando resumo errado [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 07/07/2018 - 22:01h

Olá, estou apredendo a usar a função SHA1 da openssl e acho que tive alguns problemas iniciais com ela, pois parece que a função ou o código que escrevi não estão retornando o resultado esperado.

Segue o código para uma análise:

#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>

//TESTE

int main(void){

char string[50], digest[SHA_DIGEST_LENGTH];

printf("Write >");
scanf("%s", string);

SHA1((unsigned char*)string, strlen(string), (unsigned char*)digest);

char stringMD[SHA_DIGEST_LENGTH*2+1];

for(unsigned int i=0; i<SHA_DIGEST_LENGTH; i++){

sprintf(&stringMD[i*2], "%X", (unsigned int)digest[i]);
}

printf("\n\nDigest: %s\n\n", stringMD);

return 0;
}


Quando rodo:

./sha1

Write >calcinha

Digest: ff144631ffffffff6d035d09ff1effff31ff5cffffff86


Observer que o valor gerado foi o seguinte: ff144631ffffffff6d035d09ff1effff31ff5cffffff86
Sendo que o valor certo a ser gerado seria o seguinte: fb144631e3c5d0856d035d09fd1ea2d331905c86

Por que meu código está gerando um resumo sha-1 errado?


  


2. MELHOR RESPOSTA

Fernando
phoemur

(usa Debian)

Enviado em 07/07/2018 - 23:13h

Muito simples

int main(void){

char string[50];
unsigned char digest[SHA_DIGEST_LENGTH];

printf("Write >");
scanf("%s", string);

SHA1((unsigned char*)string, strlen(string), digest);

char stringMD[SHA_DIGEST_LENGTH*2+1];

for(unsigned int i=0; i<SHA_DIGEST_LENGTH; i++){

sprintf(&stringMD[i*2], "%02x", (unsigned int)digest[i]);
}

printf("\n\nDigest: %s\n\n", stringMD);

return 0;
}


o digest deve ser unsigned char, não char...
quando você faz o cast que está dando errado...

abraços

______________________
https://github.com/phoemur

3. Re: Função 'SHA1' da openssl gerando resumo errado [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 08/07/2018 - 12:57h

phoemur escreveu:

Muito simples

int main(void){

char string[50];
unsigned char digest[SHA_DIGEST_LENGTH];

printf("Write >");
scanf("%s", string);

SHA1((unsigned char*)string, strlen(string), digest);

char stringMD[SHA_DIGEST_LENGTH*2+1];

for(unsigned int i=0; i<SHA_DIGEST_LENGTH; i++){

sprintf(&stringMD[i*2], "%02x", (unsigned int)digest[i]);
}

printf("\n\nDigest: %s\n\n", stringMD);

return 0;
}


o digest deve ser unsigned char, não char...
quando você faz o cast que está dando errado...

abraços

______________________
https://github.com/phoemur


Mas porque fazer cast dá errado?




4. Re: Função 'SHA1' da openssl gerando resumo errado [RESOLVIDO]

Fernando
phoemur

(usa Debian)

Enviado em 08/07/2018 - 17:08h

Porque a saída da função (digest) é em unsigned char...

unsigned char pode ter um valor inteiro de 0 a 255
Já char pode ser de -127 a +127...

Quando você faz o cast de um pra outro e o valor não cabe no tipo coisas bizarras acontecem (undefined behavior)
When a value with integer type is converted to another integer type other than _Bool, if [...] the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.


Por exemplo:
char foo = 255; 

Gera o seguinte Warning:
warning: overflow in implicit constant conversion


E depois ao executar
printf("%d\n", foo); 

Aqui gera a saída: -1
Mas dependendo do compilador pode ser qualquer coisa...




______________________
https://github.com/phoemur


5. Re: Função 'SHA1' da openssl gerando resumo errado [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 08/07/2018 - 23:49h

Sei que o tópico já está marcado como resolvido, mas permitam-me uma palavrinha.

Tenho a impressão de que o problema não é a conversão entre char e unsigned char, mas sim a conversão de char para unsigned int (que passa implicitamente por uma conversão para int primeiro, e depois de int para unsigned). Converter entre versões com sinal e sem sinal de um mesmo tipo básico deveria ser uma operação totalmente segura.

Mas os problemas maiores do código original estavam na chamada a sprintf(): além de faltar a especificação que garantisse a largura mínima de 2 caracteres, faltou uma operação que limitasse o valor máximo do inteiro obtido a partir da conversão do caráter. Se se tivesse feito algo como “(unsigned)variavel_char & 255u”, provavelmente teria dado o resultado certo (mas eu não testei).






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts