簡體   English   中英

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

[英]How to calculate the MD5 hash of a large file in C?

我正在用C語言編寫OpenSSL庫。

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

據我所知,我需要將整個文件作為char數組加載到RAM中,然后調用hash函數。 但是如果文件大約是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 <stdio.h>
#include <openssl/md5.h>

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()函數以塊的形式處理它以生成哈希。 如果您擔心將其作為“原子”操作,可能需要鎖定文件以防止其他人在操作期間更改它。

最佳答案是正確的,但沒有提到:對於每個使用的緩沖區大小,散列的值將不同。 該值將在哈希值之間保持一致,因此相同的緩沖區大小將每次生成相同的哈希值,但是如果此哈希值將在以后與相同數據的哈希值進行比較,則必須為每個調用使用相同的緩沖區大小。

此外,如果你想確保你的摘要代碼正常運行,並上網比較你的哈希與在線哈希網站,它似乎使用緩沖區長度為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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM