【问题标题】:md5sum of file in Linux CLinux C中文件的md5sum
【发布时间】:2011-03-24 16:00:27
【问题描述】:

我想在 Linux C 中查找文件的 md5sum,是否有任何 API 可以发送文件名以获取该文件的 md5sum。

【问题讨论】:

    标签: c linux hash md5


    【解决方案1】:

    有代码here

    此外,openssl 库具有 md5 函数(来自 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);        
    }
    

    【讨论】:

    • 感谢您在这里分享示例! (out 应该是 unsigned char 和长度 MD5_DIGEST_LENGTH 的数组。最后一个 printf("\n"); 避免在我的终端上看到虚假字符。)
    • @Andre Holzner:已修复。干杯。
    • 当将其转换为使用 FILE 进行输入时,我必须使用 fread 而不是 read,否则我会得到不同的哈希
    【解决方案2】:

    您可以使用popen 运行md5sum 并读取输出:

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

    【讨论】:

      【解决方案3】:

      您可以使用mhash 库(许可证为 LGPL)。在 Debian 系统上:

      sudo apt-get install libmhash-dev
      

      参见手册页man 3 mhash

      但我认为你不能只给它一个文件名。你必须自己打开文件,读取数据,然后将数据提供给这个库的函数。

      【讨论】:

        【解决方案4】:

        对 Raja 提出的问题的简单回答并使用 sje397 的回答,可以在 C 程序中计算文件的 md5sum,如下所示。另请注意,当您可以使用 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;
        }
        

        【讨论】:

          【解决方案5】:

          如果您希望为文件生成 MD5 哈希并将其与字符串进行比较,您可以使用它。

          在这里,我使用了D'Nabre's code from another SO answerMichael Foukarakis's hex string to byte array code from this SO answer。 它需要与 OpenSSL 库 (gcc md5.c -o md5 -lssl) 链接才能工作。

          示例用法:

          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;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-09-13
            • 1970-01-01
            • 2014-05-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多