2011-10-21 144 views
8

我想使用OpenSSL/libcrypto来编写C函数来计算文件的SHA256总和。我将我的代码基于Adam Lamer的C++示例here使用OpenSSL计算和打印文件的SHA256哈希

这里是我的代码:

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; 
} 

是这个....看看下面的计算总和的实例文件的问题:

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

我也得到*砸检测栈*代码完成执行时。

有没有人看到我在做什么错了?

谢谢!

+0

我宣布了原型。 – dan6470

+0

为什么const int bufSize的大小是32768?它可能是或多或少的 –

回答

12

看起来你的输出中有很多'0xff'块,而好字符串中的对应块有高位设置...也许是某处的符号扩展问题。

是否使:

char hash[SHA256_DIGEST_LENGTH]; 

符号,就像:

unsigned char hash[SHA256_DIGEST_LENGTH]; 

帮助? (特别是在签名sha256_hash_string。)

+0

修复它!谢谢!我在Ubuntu上使用gcc。 – dan6470

+1

我对little-endianess的评论是错误的,所以我把它删除了...... Adam每次输入都是负数时,都有正确的解释8个字节。这是一个很好的例子,为什么在处理“字节”而不是“字符串”时,应该使用'unsigned char'(或uint8或其变体之一)。裸露的'char'应该保留给ASCII字符。 –

11

您正在打印一个签署char作为一个整数。如果该字节为负值,则将其转换为signed int(在调用sprintf默认参数促销),然后将其转换为unsigned int(通过%x格式说明符)并打印出来。

因此,字节A0是-96作为有符号字节,它被转换为-96作为signed int,它是十六进制的0xFFFFFFA0,因此它被打印为FFFFFFA0。

在打印之前解决这个问题,情况下,每个字节的unsigned char

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

你得到关于堆栈溢出的警告,因为有附近的哈希结束一个符号字节,所以你写当您打算只写入2个字节时,偏移量为58的8个字节FFFFFFB7。这导致了buffer overflow,这恰好在此处被检测到,因为编译器可能在返回值之前在堆栈中插入了警戒区域或安全cookie,并且它检测到该警戒区域被无意中修改。

+0

就是这样!感谢您的解释! – dan6470