2012-04-25 13 views
13

मैं ओपनएसएसएल लाइब्रेरी का उपयोग कर सी में लिख रहा हूं।सी में बड़ी फाइल के MD5 हैश की गणना कैसे करें?

मैं md5 का उपयोग कर एक बड़ी फ़ाइल के हैश की गणना कैसे कर सकता हूं?

जैसा कि मुझे पता है, मुझे रैम में एक पूर्ण फ़ाइल को चार सरणी के रूप में लोड करने की आवश्यकता है और फिर हैश फ़ंक्शन को कॉल करें। लेकिन क्या होगा अगर फ़ाइल लगभग 4 जीबी लंबी है? एक बुरा विचार की तरह लगता है।

सोल्व: 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); 
+0

मुझे इसकी आवश्यकता जानने के लिए उत्सुकता है? यह निश्चित रूप से एक बुरा विचार हो सकता है अगर यह थ्रेड सुरक्षित नहीं है, क्योंकि यह कार्यक्रम को विस्तारित अवधि और पीओ के लिए अवरुद्ध कर सकता है। उपयोगकर्ता – crockpotveggies

+5

फ़ाइल एन्क्रिप्ट करना एमडी 5 जैसे हैश फ़ंक्शन के साथ इसे उतना ही नहीं है। क्या आप वास्तव में हैश का मतलब है, या आप फ़ाइल को एन्क्रिप्ट करना चाहते हैं? – Oleksi

+7

एमडी 5 स्ट्रीम-आधारित है। आपको पूरे 4 जीबी को स्मृति में लोड करने की आवश्यकता नहीं है - आप इसे टुकड़ों में पढ़ते हैं। –

उत्तर

28

उदाहरण

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 
+0

हस्ताक्षरित चार डेटा [1024]; जबकि ((बाइट्स = फ़्रेड (डेटा, 1, 1024, इनफाइल))! = 0) हस्ताक्षर किए गए चार डेटा [4096]; जबकि ((बाइट्स = फ़्रेड (डेटा, 1, 40 9 6, इनफाइल))! = 0) ? – user1031143

3

आप एक बार में स्मृति में पूरी फ़ाइल लोड करने के लिए नहीं है। हैश का उत्पादन करने के लिए आप इसे संसाधित करने के लिए MD5_Init(), MD5_Update() and MD5_Final() फ़ंक्शंस का उपयोग कर सकते हैं। यदि आप इसे "परमाणु" ऑपरेशन करने के बारे में चिंतित हैं, तो ऑपरेशन के दौरान किसी और को बदलने से रोकने के लिए फ़ाइल को लॉक करना आवश्यक हो सकता है।

6

पहला, एमडी 5 एक हैशिंग एल्गोरिदम है। यह कुछ भी एन्क्रिप्ट नहीं करता है।

वैसे भी, आप जो भी आकार पसंद करते हैं, उसमें आप फ़ाइल को पढ़ सकते हैं। एक बार MD5_Init पर कॉल करें, फिर फ़ाइल से पढ़े गए प्रत्येक डेटा के साथ MD5_Update पर कॉल करें। जब आप पूरा कर लें, तो परिणाम प्राप्त करने के लिए MD5_Final पर कॉल करें।

+0

मैंने कोशिश की है।मैंने फ़ाइल को 16-बाइट ब्लॉक में विभाजित कर दिया है और उन्हें MD5_Update पर पास कर दिया है, लेकिन हैश गलत था। – user1256821

+1

तो अपने कोड में बग को ठीक करें जिससे हैश गलत हो गया है। (इसके अलावा, 16 बाइट ब्लॉक धीमे हो जाएंगे। आप पट्टे पर 64 केबी ब्लॉक का उपयोग करके बहुत बेहतर प्रदर्शन करेंगे।) –

1

शीर्ष जवाब सही है, लेकिन कुछ का उल्लेख नहीं था: हैश का मान प्रत्येक बफर के लिए अलग होगा आकार का इस्तेमाल किया। मूल्य हैश में संगत होगा, इसलिए वही बफर आकार हर समय एक ही हैश का उत्पादन करेगा, हालांकि यदि बाद में उसी डेटा के हैश के खिलाफ इस हैश की तुलना की जाएगी, तो प्रत्येक कॉल के लिए उसी बफर आकार का उपयोग किया जाना चाहिए।

इसके अतिरिक्त, यदि आप यह सुनिश्चित करना चाहते हैं कि आपका पाचन कोड सही तरीके से कार्य करता है, और ऑनलाइन हैशिंग वेबसाइटों के साथ अपने हैश की तुलना करने के लिए ऑनलाइन जाएं, ऐसा लगता है कि वे 1 की बफर लंबाई का उपयोग करते हैं। यह एक दिलचस्प विचार भी लाता है: यह एक बड़ी फ़ाइल में हैश की एक बफर लंबाई का उपयोग करने के लिए पूरी तरह से स्वीकार्य है, इसमें केवल अधिक समय लगेगा (डुह)।

तो अंगूठे का मेरा नियम यह है कि यह केवल आंतरिक उपयोग के लिए है, तो मैं एक बड़ी फ़ाइल के लिए बफर लंबाई निर्धारित कर सकता हूं, लेकिन अगर इसे अन्य प्रणालियों के साथ अच्छा खेलना है, तो बफर की लंबाई 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; 
} 
संबंधित मुद्दे