使用OpenSSL计算并打印文件的SHA256哈希值

10

我正在尝试编写一个使用OpenSSL/libcrypto计算文件SHA256摘要的C函数。 我的代码基于Adam Lamer的c++示例(链接)

这是我的代码:

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

当代码执行完成后,我也会收到“stack smashing detected”的提示。

有没有人发现我的问题在哪里?

谢谢!


为什么const int bufSize的大小被固定为32768?它可能会更大或更小。 - Sanjay Kumar
2个回答

15

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

尝试将:

char hash[SHA256_DIGEST_LENGTH];

unsigned, like:


无符号类型,例如:
unsigned char hash[SHA256_DIGEST_LENGTH];

求助?(特别是在sha256_hash_string的签名中。)


解决了!谢谢你!我正在使用gcc的Ubuntu系统。 - dan6470
1
我的有关小端序的评论是错误的,所以我删除了它... Adam 对于每次输入为负时打印8个字节的解释是正确的。这是一个很好的例子,说明在处理“字节”而不是“字符串字符”时,应该使用'unsigned char'(或uint8或其变体之一)。裸的'char'应该保留给ASCII字符。 - P.T.

12
你正在将一份有符号的char作为整数输出。如果字节是负数,则会被转换为signed int(在调用sprintf时的默认参数升级),然后通过%x格式说明符将其转换为unsigned int并打印出来。
所以,字节A0作为有符号字节是-96,它被转换为signed int仍是-96,它的十六进制表示是0xFFFFFFA0,因此它被输出为FFFFFFA0。
为了解决这个问题,在打印之前将每个字节转换为unsigned char类型。
sprintf(..., (unsigned char)hash[i]);

你之所以收到了栈溢出的警告,是因为哈希表末尾附近有一个有符号字节(signed byte),所以当你本意只写入2个字节时,实际上在偏移量58处写入了8个字节FFFFFFB7。这导致了缓冲区溢出,这里检测到了它,很可能是因为编译器在返回值之前在堆栈中插入了一个保护区域或安全 cookie,并检测到该保护区域被意外修改。


就是这样了!感谢解释! - dan6470

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接