web-dev-qa-db-fra.com

md5sum de fichier sous Linux C

Je veux trouver md5sum d'un fichier dans Linux C, y a-t-il une API où je peux envoyer le nom du fichier pour obtenir md5sum de ce fichier.

24
Raja

Il y a un code ici .

De plus, les bibliothèques openssl ont des fonctions md5 (à partir de ici ):

#include <openssl/md5.h>
#include <unistd.h>
int main()
{
    int n;
    MD5_CTX c;
    char buf[512];
    ssize_t bytes;
    unsigned char out[MD5_DIGEST_LENGTH];

    MD5_Init(&c);
    bytes=read(STDIN_FILENO, buf, 512);
    while(bytes > 0)
    {
        MD5_Update(&c, buf, bytes);
        bytes=read(STDIN_FILENO, buf, 512);
    }

    MD5_Final(out, &c);

    for(n=0; n<MD5_DIGEST_LENGTH; n++)
        printf("%02x", out[n]);
    printf("\n");

    return(0);        
}
34
sje397

Vous pouvez utiliser popen pour exécuter md5sum et lire le résultat:

#include <stdio.h>
#include <ctype.h>

#define STR_VALUE(val) #val
#define STR(name) STR_VALUE(name)

#define PATH_LEN 256
#define MD5_LEN 32

int CalcFileMD5(char *file_name, char *md5_sum)
{
    #define MD5SUM_CMD_FMT "md5sum %." STR(PATH_LEN) "s 2>/dev/null"
    char cmd[PATH_LEN + sizeof (MD5SUM_CMD_FMT)];
    sprintf(cmd, MD5SUM_CMD_FMT, file_name);
    #undef MD5SUM_CMD_FMT

    FILE *p = popen(cmd, "r");
    if (p == NULL) return 0;

    int i, ch;
    for (i = 0; i < MD5_LEN && isxdigit(ch = fgetc(p)); i++) {
        *md5_sum++ = ch;
    }

    *md5_sum = '\0';
    pclose(p);
    return i == MD5_LEN;
}

int main(int argc, char *argv[])
{
    char md5[MD5_LEN + 1];

    if (!CalcFileMD5("~/testfile", md5)) {
        puts("Error occured!");
    } else {
        printf("Success! MD5 sum is: %s\n", md5);
    }
}
12
adf88

Vous pouvez utiliser la bibliothèque mhash (la licence est LGPL). Sur les systèmes Debian:

Sudo apt-get install libmhash-dev

Voir la page de manuel man 3 mhash

Mais je ne pense pas que vous puissiez simplement lui donner le nom d’un fichier. Vous devez ouvrir le fichier vous-même, lire les données et les alimenter aux fonctions de cette bibliothèque.

3
Craig McQueen

Si vous souhaitez générer un hachage MD5 pour un fichier et le comparer à une chaîne, vous pouvez l'utiliser.

Ici, j'ai utilisé le code de D'Nabre provenant d'un autre SO réponse et de la chaîne hexagonale de Michael Foukarakis en octets du code tableau de cette SO réponse . Il doit être lié à la bibliothèque OpenSSL (gcc md5.c -o md5 -lssl) pour fonctionner. 

Exemple d'utilisation: 

unsigned char *file_hash = md5_for_file("~/testfile");
if (md5_is_match_str(file_hash, "b7be4ec867f9b0286b91dd40178774d6")) {
    printf("Match\n");
} else {
    printf("Mismatch\n");
}

free(file_hash);

md5.h:

#ifndef MD5_H
#define MD5_H

/** Caller to free result */
unsigned char *md5_for_file(char *filename);

/** md5_1 & md5_2 maybe NULL */
int md5_is_match(unsigned char *md5_1, unsigned char *md5_2);

/** md5 maybe NULL */
int md5_is_match_str(unsigned char *md5, const char *md5_str);

#endif //MD5_H

md5.c:

#include "md5.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/md5.h>

// Print the MD5 sum as hex-digits.
void print_md5_sum(unsigned char *md) {
    int i;
    for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
        printf("%02x", md[i]);
    }
    printf("\n");
}

// Get the size of the file by its file descriptor
unsigned long get_size_by_fd(int fd) {
    struct stat statbuf;
    if (fstat(fd, &statbuf) < 0) exit(-1);
    return statbuf.st_size;
}

unsigned char *md5_for_file(char *filename) {
    int file_descript;
    unsigned long file_size;
    char *file_buffer;
    unsigned char *result = malloc(sizeof(*result) * MD5_DIGEST_LENGTH);
    if (NULL == result) {
        printf("malloc failed\n");
        goto END;
    }

    printf("using file:\t%s\n", filename);

    file_descript = open(filename, O_RDONLY);
    if (file_descript < 0) exit(-1);

    file_size = get_size_by_fd(file_descript);
    printf("file size:\t%lu\n", file_size);

    file_buffer = mmap(0, file_size, PROT_READ, MAP_SHARED, file_descript, 0);
    MD5((unsigned char *) file_buffer, file_size, result);
    munmap(file_buffer, file_size);

    print_md5_sum(result);
    END:
    return result;
}

int md5_is_match(unsigned char *md5_1, unsigned char *md5_2) {
    if (!md5_1 || !md5_2) {
        return 0;
    }

    int i;
    for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
        if (md5_1[i] != md5_2[i]) {
            return 0;
        }
    }

    return 1;
}

int md5_is_match_str(unsigned char *md5, char *md5_str) {
    if (!md5 || !md5_str) { return 0; }

    /** Make byte arrary from md5_str */
    unsigned char md5_arr[MD5_DIGEST_LENGTH] = {0};

    const char *pos = md5_str;
    size_t count = 0;

    /* WARNING: no sanitization or error-checking whatsoever */
    for (count = 0; count < sizeof(md5_arr) / sizeof(md5_arr[0]); count++) {
        sscanf(pos, "%2hhx", &md5_arr[count]);
        pos += 2;
    }

    for (count = 0; count < sizeof(md5_arr) / sizeof(md5_arr[0]); count++) {
        printf("%02x", md5_arr[count]);
    }
    printf("\n");

    /** actual comparison */
    if (memcmp(md5, md5_arr, MD5_DIGEST_LENGTH)) {
        return 0;
    }

    return 1;
}
0
Shoaib Ahmed

Une réponse facile à la question posée par Raja et à l'aide de la réponse de sje397, la somme md5 d'un fichier peut être calculée dans le programme C comme indiqué ci-dessous. Notez également qu'il n'est pas nécessaire d'écrire la commande de lecture deux fois lorsque vous pouvez utiliser la boucle do while.

int calculate_md5sum(char *filename)
{
  //open file for calculating md5sum
  FILE *file_ptr;
  file_ptr = fopen(filename, "r");
  if (file_ptr==NULL)
  {
    perror("Error opening file");
    fflush(stdout);
    return 1;
  }

  int n;
  MD5_CTX c;
  char buf[512];
  ssize_t bytes;
  unsigned char out[MD5_DIGEST_LENGTH];

  MD5_Init(&c);
  do
  {
    bytes=fread(buf, 1, 512, file_ptr);
    MD5_Update(&c, buf, bytes);
  }while(bytes > 0);

  MD5_Final(out, &c);

  for(n=0; n<MD5_DIGEST_LENGTH; n++)
          printf("%02x", out[n]);
  printf("\n");
  return 0;
}