C 使用fgets时,哈希与sha1sum不同

C 使用fgets时,哈希与sha1sum不同,c,openssl,fgets,C,Openssl,Fgets,我正在尝试编写一个简单的哈希程序。代码如下: #include <openssl/evp.h> #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { unsigned char hash[EVP_MAX_MD_SIZE]; unsigned hash_size; unsigned i; char s[100]; EVP_MD

我正在尝试编写一个简单的哈希程序。代码如下:

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

int main(int argc, char *argv[])
{
    unsigned char hash[EVP_MAX_MD_SIZE];
    unsigned hash_size;
    unsigned i;
    char s[100];

    EVP_MD_CTX *ctx = EVP_MD_CTX_create();
    EVP_MD_CTX_init(ctx);
    EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);

    while (fgets(s, sizeof(s), stdin))
    {
        EVP_DigestUpdate(ctx, s, strnlen(s, sizeof(s) - 1));
    }

    EVP_DigestFinal_ex(ctx, hash, &hash_size);
    EVP_MD_CTX_destroy(ctx);

    for (i = 0; i < hash_size; ++i)
    {
        printf("%02x", hash[i]);
    }

    printf("\n");

    EVP_MD_CTX_cleanup(ctx);
    return 0;
}
不幸的是,我生成的SHA与
sha1sum
返回的内容不匹配:

$ sha1sum testfile
05a5e29ba59164ceee6bffbaec283ae5a6ecd66f  testfile
$ myhashprog < testfile
d8e5c7f4360beb2cabf7275d15293a711e5dfeb3
$sha1sum测试文件
05A5E29BA59164CEEE6BFBAEC283AE5A6ECD66F测试文件
$myhashprog
我做错了什么


我注意到文件中有一个
0x00
,看起来像字符串终止符,但我不确定如何处理它。可能
fgets()
在这种情况下不是从文件中读取的合适函数…

我通过使用
read()
而不是
fgets()
解决了这个问题:


问题是,尽管
fgets()
将读取所有字节,但它不会返回读取的字节数,因此除非您事先知道输入的大小,否则无法可靠地确定缓冲区的相关大小。

是的,不要使用fgets,只需读取原始字节(您已经知道文件大小对应的字节数).如果它是从管子里出来的呢?那么你必须一直读下去,直到你得到“流的尽头”。您可以分块更新摘要,无需一次将其全部读入内存。无论哪种方式,读取原始字节。不要对零字节进行特殊处理。使用
read()
效果很好。由于没有正式答案,我倾向于删除这个问题。有人介意吗?@Stephen-我建议把这个问题留待讨论。我快速搜索了一个副本,但没有找到。此外,有人可能会对使用
EVP\u MD\u CTX\u destroy
EVP\u MD\u CTX\u cleanup
发表评论。我认为一个是超级的,但是我手头没有源代码可以检查。如果没有答案,也许你可以提供一个正式的答案。它可能会对未来的访问者有所帮助。这里最突出的一点是,
fgets
想要读取字符串,并在零字节处停止<代码>读取
将读取尽可能多的字节。谢谢,我已经更新了我的答案,使其更全面。
$ sha1sum testfile
05a5e29ba59164ceee6bffbaec283ae5a6ecd66f  testfile
$ myhashprog < testfile
d8e5c7f4360beb2cabf7275d15293a711e5dfeb3
while ((bytes = read(STDIN_FILENO, s, sizeof(s))) > 0)
{
    EVP_DigestUpdate(ctx, s, bytes);
}