2010-08-03 17 views
22

Quiero encontrar md5sum de un archivo en Linux C, ¿Hay alguna API donde pueda enviar un nombre de archivo para obtener md5sum de ese archivo?md5sum de archivo en Linux C

Respuesta

32

Hay código here.

Además, las librerías OpenSSL tienen funciones MD5 (de here):

#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);   
} 
+1

gracias por compartir el ejemplo aquí! ('out' debe ser un conjunto de' unsigned char' y length 'MD5_DIGEST_LENGTH'. Y un' printf ("\ n"); 'final evita ver caracteres espurios en mi terminal.) –

+0

@Andre Holzner: Reparado. Aclamaciones. – sje397

+0

Al convertir esto para usar un 'FILE' para la entrada, tuve que usar fread en lugar de read, de lo contrario estaba obteniendo un hash diferente – nmz787

12

Puede utilizar popen para funcionar md5sum y leer la salida:

#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); 
    } 
} 
2

Usted puede usar la biblioteca mhash (licencia es LGPL). En los sistemas Debian:

sudo apt-get install libmhash-dev 

Consulte la página del manual man 3 mhash

Pero no creo que sólo se puede dar el nombre de un archivo. Debe abrir el archivo usted mismo, leer los datos y alimentar los datos a las funciones de esta biblioteca.

0

Si está buscando generar hash MD5 para un archivo y compararlo con una cadena, puede usarlo.

Aquí, he usado D'Nabre's code from another SO answer y Michael Foukarakis's hex string to byte array code from this SO answer. Tiene que estar enlazado con la biblioteca OpenSSL (gcc md5.c -o md5 -lssl) para que funcione. el uso

muestra:

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

Una respuesta fácil a la pregunta formulada por Raja y el uso de respuesta de sje397 , el md5sum de un archivo se puede calcular dentro del programa C como se muestra a continuación. Observe también que no es necesario escribir el comando de lectura dos veces cuando puede usar el ciclo 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; 
}