1

I have made many researches about MD5 of an xls file but my effort seems be in vain I tried to used lirary and recommendation in this link "https://stackoverflow.com/questions/27858288/calculate-md5-for-a-file-in-c-language" but , still give wrong result , can you help me ??

Community
  • 1
  • 1
M.A.E
  • 33
  • 2
  • `MD5` of an xls file? it doesn't make sense, you should read the file to a buffer, and then use an implementation of `md5` hashing algorithm on the buffer. – Iharob Al Asimi Jan 12 '15 at 17:45
  • 2
    The structural contents of the file are irrelevant - MD5 produces a message digest for any stream of bytes. – maerics Jan 12 '15 at 17:48
  • The question you link to, is using `fp=fopen(file,"r");` to open a file. That would give a wrong result for any binary file, including xls files. – wimh Jan 12 '15 at 17:48
  • @M.A.E The question to which you're referring seems to be deleted ... – TheByeByeMan Jan 19 '15 at 15:51

3 Answers3

3

MD5 of xls file is very same of MD5 of any other kind of file since it operates on bytes. See by example openssl implementation openssl/crypto/md5/md5.c and md5test.c ( code is in git://git.openssl.org/openssl.git ).

philippe lhardy
  • 3,096
  • 29
  • 36
3

Well I used to answer the link you gave but then the question was closed. The idea is as follows. First read the file into a buffer. You can do this using following function:

unsigned char * readFile(const char *path)
{
    FILE * pFile;
    long lSize;
    unsigned char * buffer;
    size_t result;

    pFile = fopen (path , "rb" );
    if (pFile==NULL) {fputs ("File error",stderr); exit (1);}

    // obtain file size:
    fseek (pFile , 0 , SEEK_END);
    lSize = ftell (pFile);
    rewind (pFile);

    // allocate memory to contain the whole file:
    buffer = malloc (sizeof(char)*lSize);
    if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

    // copy the file into the buffer:
    result = fread (buffer,1,lSize,pFile);
    if (result != lSize) {fputs ("Reading error",stderr); exit (3);}


    // terminate
    fclose (pFile);

    return buffer;
}

Read the file

unsigned char * data = readFile("c:\\file.xls");

Then you must apply MD5 on this buffer of data. You can use code similar to the one in that question (though I am not sure which library/implementation of md5 author of that question used). e.g.,

 char hash[64] = {0};
 md5_byte_t digest[16] = {0};
 md5_init(&state);
 md5_append(&state, (const md5_byte_t  *)data, filesize);
 md5_finish(&state,digest);
 int i=0;      
 for(i; i<16; i++)
 {
      snprintf(hash + i*2,sizeof(hash),"%02x",digest[i]);
 }

Now hash should store the hash of the file, encoded in hexadecimal string. ps. Indeed that sample is incorrectly using strlen with binary file. That is why I suggested the readFile method above; that function also contains code to get file size - you can use that code to get file size and then pass the file size to md5_append method.

ps. also don't forget to free data when you are done with it.

Giorgi Moniava
  • 27,046
  • 9
  • 53
  • 90
2

The problem is that your example uses strlen to determine the file size. But .xls format is binary, so strlen will not work properly.

Adapt the function to return the total data read from the file, and it should work.

Edit. Try something like this code:

void *addr;
struct stat s;
int ret, fd;

ret = stat(filename, &s);
if (ret) {
    fprintf(stderr, "Error while stat()ing file: %m\n");
    return -1;
}

fd = open(filename, O_RDONLY);;
if (fd < 0) {
    fprintf(stderr, "Error while opening file: %m\n");
    return -1;
}

addr = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED) {
    fprintf(stderr, "Error while mapping file: %m\n");
    close(fd);
    return -1;
}

md5_init(&state);
md5_append(&state,addr, s.st_size);
md5_finish(&state,digest);
Jonatan Goebel
  • 1,107
  • 9
  • 14