2011-10-21 45 views
8

Estoy intentando escribir una función C usando OpenSSL/libcrypto para calcular la suma SHA256 de un archivo. Estoy basando mi código en el ejemplo de C++ de Adam Lamer here.Calcular e imprimir el hash SHA256 de un archivo usando OpenSSL

Aquí está mi código:

int main (int argc, char** argv) 
{ 
    char calc_hash[65]; 

    calc_sha256("file.txt", calc_hash); 
} 

int calc_sha256 (char* path, char output[65]) 
{ 
    FILE* file = fopen(path, "rb"); 
    if(!file) return -1; 

    char hash[SHA256_DIGEST_LENGTH]; 
    SHA256_CTX sha256; 
    SHA256_Init(&sha256); 
    const int bufSize = 32768; 
    char* buffer = malloc(bufSize); 
    int bytesRead = 0; 
    if(!buffer) return -1; 
    while((bytesRead = fread(buffer, 1, bufSize, file))) 
    { 
     SHA256_Update(&sha256, buffer, bytesRead); 
    } 
    SHA256_Final(hash, &sha256); 

    sha256_hash_string(hash, output); 
    fclose(file); 
    free(buffer); 
    return 0; 
}  

void sha256_hash_string (char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65]) 
{ 
    int i = 0; 

    for(i = 0; i < SHA256_DIGEST_LENGTH; i++) 
    { 
     sprintf(outputBuffer + (i * 2), "%02x", hash[i]); 
    } 

    outputBuffer[64] = 0; 
} 

está presente .... echar un vistazo a las sumas calculadas por debajo de un archivo de ejemplo El problema:

Known good SHA256: 6da032d0f859191f3ec46a89860694c61e65460d54f2f6760b033fa416b73866 
Calc. by my code: 6dff32ffff59191f3eff6affff06ffff1e65460d54ffff760b033fff16ff3866 

también consigo * pila destrozo detecta * cuando el código ha terminado de ejecutarse.

¿Alguien ve lo que estoy haciendo mal?

Gracias!

+0

Tengo prototipos declarados. – dan6470

+0

¿por qué const int bufSize se soluciona con el tamaño de 32768? podría ser más o menos –

Respuesta

12

Parece que hay muchos bloques '0xff' en su salida, y los bloques correspondientes en la cadena correcta tienen el bit alto establecido ... tal vez un problema de extensión de señal en alguna parte.

Si realizo:

char hash[SHA256_DIGEST_LENGTH]; 

sin firmar, como:

unsigned char hash[SHA256_DIGEST_LENGTH]; 

ayuda? (Especialmente en la firma de sha256_hash_string.)

+0

¡Eso lo solucionó! ¡Gracias! Estoy en Ubuntu usando gcc. – dan6470

+1

Mi comentario sobre little-endianess era incorrecto, así que lo eliminé ... Adam tenía la explicación correcta sobre la impresión de 8 bytes cada vez que la entrada era negativa. Este es un buen ejemplo de por qué, cuando se trata de "bytes" y no de "caracteres de cadena", debe usar "char sin signo" (o uint8 o una de sus variantes). El 'char' desnudo debe reservarse para caracteres ASCII. –

11

Usted está imprimiendo una firmaronchar como un entero. Si el byte es negativo, se convierte a signed int (el argumento predeterminado promociones en la llamada al sprintf), y luego se convierte en unsigned int (mediante el especificador de formato) y se imprime.

Así, el byte es A0 -96 como un byte con signo, que se convierte a -96 como signed int, que es 0xFFFFFFA0 en hexadecimal, por lo que se imprime como FFFFFFA0.

Para solucionar este problema, caso cada byte a un unsigned char antes de imprimir:

sprintf(..., (unsigned char)hash[i]); 

que está recibiendo la advertencia sobre la pila rompiendo porque hay un byte con signo cerca del final del hachís, por lo que está escrito los 8 bytes de FFFFFFB7 en el desplazamiento 58 cuando intentaba solo escribir 2 bytes. Esto da como resultado un buffer overflow, que se detecta aquí porque el compilador probablemente insertó un área de guardia o una cookie de seguridad en la pila antes del valor de retorno, y detectó que ese área de guardia se modificó inadvertidamente.

+0

¡Eso es todo! Gracias por la explicación! – dan6470

Cuestiones relacionadas