如何计算C中大文件的MD5哈希值?

我使用OpenSSL库在C语言编写。

如何使用md5计算大文件的哈希值?

据我所知,我需要将整个文件作为char数组加载到RAM中,然后调用哈希函数。 但是如果文件大约是4Gb呢? 听起来不错。

解决 :感谢askovpen ,我发现了我的错误。 我用过

while ((bytes = fread (data, 1, 1024, inFile)) != 0) MD5_Update (&mdContext, data, 1024); 

 while ((bytes = fread (data, 1, 1024, inFile)) != 0) MD5_Update (&mdContext, data, bytes); 

gcc -g -Wall -o file file.c -lssl -lcrypto

 #include  #include  int main() { unsigned char c[MD5_DIGEST_LENGTH]; char *filename="file.c"; int i; FILE *inFile = fopen (filename, "rb"); MD5_CTX mdContext; int bytes; unsigned char data[1024]; if (inFile == NULL) { printf ("%s can't be opened.\n", filename); return 0; } MD5_Init (&mdContext); while ((bytes = fread (data, 1, 1024, inFile)) != 0) MD5_Update (&mdContext, data, bytes); MD5_Final (c,&mdContext); for(i = 0; i < MD5_DIGEST_LENGTH; i++) printf("%02x", c[i]); printf (" %s\n", filename); fclose (inFile); return 0; } 

结果:

 $ md5sum file.c 25a904b0e512ee546b3f47574703d9fc file.c $ ./file 25a904b0e512ee546b3f47574703d9fc file.c 

首先,MD5是一种散列算法。 它不加密任何东西。

无论如何,您可以以任何您喜欢的大小读取文件。 调用MD5_Init一次,然后使用从文件中读取的每个数据块调用MD5_Update 。 完成后,调用MD5_Final获取结果。

您不必一次将整个文件加载到内存中。 您可以使用函数MD5_Init(),MD5_Update()和MD5_Final()以块的forms处理它以生成散列。 如果您担心将其设置为“primefaces”操作,则可能需要锁定文件以防止其他人在操作期间更改它。

最佳答案是正确的,但没有提到:对于每个使用的缓冲区大小,散列的值将是不同的。 该值将在哈希值之间保持一致,因此相同的缓冲区大小将每次生成相同的哈希值,但是如果此哈希值将在以后与相同数据的哈希值进行比较,则必须为每个调用使用相同的缓冲区大小。

此外,如果你想确保你的摘要代码正常运行,并上网比较你的哈希与在线哈希网站,它们似乎使用缓冲区长度为1.这也带来了一个有趣的想法:它是完全可以接受的使用缓冲区长度为1来散列大文件,它只需要更长的时间( duh )。

所以我的经验法则是,如果它仅供内部使用,那么我可以相应地为大文件设置缓冲区长度,但如果必须与其他系统一起使用,那么将缓冲区长度设置为1并处理时间后果。

 int hashTargetFile(FILE* fp, unsigned char** md_value, int *md_len) { #define FILE_BUFFER_LENGTH 1 EVP_MD_CTX *mdctx; const EVP_MD *md; int diglen; //digest length int arrlen = sizeof(char)*EVP_MAX_MD_SIZE + 1; int arrlen2 = sizeof(char)*FILE_BUFFER_LENGTH + 1; unsigned char *digest_value = (char*)malloc(arrlen); char *data = (char*)malloc(arrlen2); size_t bytes; //# of bytes read from file mdctx = EVP_MD_CTX_new(); md = EVP_sha512(); if (!mdctx) { fprintf(stderr, "Error while creating digest context.\n"); return 0; } if (!EVP_DigestInit_ex(mdctx, md, NULL)) { fprintf(stderr, "Error while initializing digest context.\n"); return 0; } while (bytes = fread(data, 1, FILE_BUFFER_LENGTH, fp) != 0) { if (!EVP_DigestUpdate(mdctx, data, bytes)) { fprintf(stderr, "Error while digesting file.\n"); return 0; } } if (!EVP_DigestFinal_ex(mdctx, digest_value, &diglen)) { fprintf(stderr, "Error while finalizing digest.\n"); return 0; } *md_value = digest_value; *md_len = diglen; EVP_MD_CTX_free(mdctx); return 1; }