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



我正在尝试使用OpenSSL/libcrypto编写C函数来计算文件的SHA256和。我的代码基于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

当代码完成执行时,我也会得到*堆栈粉碎检测*。

有人看到我做错了什么吗?

谢谢!

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

制作:

char hash[SHA256_DIGEST_LENGTH];

无符号,如:

unsigned char hash[SHA256_DIGEST_LENGTH];

帮助吗?(特别是在sha256_hash_string的签名中)

您正在将带符号的 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。这将导致缓冲区溢出,因为编译器可能在返回值之前在堆栈中插入了一个保护区域或安全cookie,并且它检测到该保护区域被无意中修改了,所以这里恰好检测到缓冲区溢出

最新更新