1. 程式人生 > >C語言計算檔案MD5

C語言計算檔案MD5

  計算MD5這種很標準的東西,一般直接使用別人寫好的了就行,本文主要針對寫好的介面測試一下如何使用的問題。

下面是MD5的實現
md5.h

#ifndef MD5_H  
#define MD5_H  

typedef struct  
{  
    unsigned int count[2];  
    unsigned int state[4];  
    unsigned char buffer[64];     
}MD5_CTX;  


#define F(x,y,z) ((x & y) | (~x & z))  
#define G(x,y,z) ((x & z) | (y & ~z))  
#define H(x,y,z) (x^y^z) #define I(x,y,z) (y ^ (x | ~z)) #define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) #define FF(a,b,c,d,x,s,ac) \ { \ a += F(b,c,d) + x + ac; \ a = ROTATE_LEFT(a,s); \ a += b; \ } #define GG(a,b,c,d,x,s,ac) \ { \ a += G(b,c,d) + x + ac; \ a = ROTATE_LEFT(a,s); \ a += b; \ } #define HH(a,b,c,d,x,s,ac) \
{ \ a += H(b,c,d) + x + ac; \ a = ROTATE_LEFT(a,s); \ a += b; \ } #define II(a,b,c,d,x,s,ac) \ { \ a += I(b,c,d) + x + ac; \ a = ROTATE_LEFT(a,s); \ a += b; \ } void MD5Init(MD5_CTX *context); void MD5Update(MD5_CTX *context,unsigned
char *input,unsigned int inputlen); void MD5Final(MD5_CTX *context,unsigned char digest[16]); void MD5Transform(unsigned int state[4],unsigned char block[64]); void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); #endif

md5.c

#include <string.h>
#include "md5.h" 


unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  

void MD5Init(MD5_CTX *context)  
{  
    context->count[0] = 0;  
    context->count[1] = 0;  
    context->state[0] = 0x67452301;  
    context->state[1] = 0xEFCDAB89;  
    context->state[2] = 0x98BADCFE;  
    context->state[3] = 0x10325476;  
}  
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen)  
{  
    unsigned int i = 0,index = 0,partlen = 0;  
    index = (context->count[0] >> 3) & 0x3F;  
    partlen = 64 - index;  
    context->count[0] += inputlen << 3;  
    if(context->count[0] < (inputlen << 3))  
        context->count[1]++;  
    context->count[1] += inputlen >> 29;  

    if(inputlen >= partlen)  
    {  
        memcpy(&context->buffer[index],input,partlen);  
        MD5Transform(context->state,context->buffer);  
        for(i = partlen;i+64 <= inputlen;i+=64)  
            MD5Transform(context->state,&input[i]);  
        index = 0;          
    }    
    else  
    {  
        i = 0;  
    }  
    memcpy(&context->buffer[index],&input[i],inputlen-i);  
}  
void MD5Final(MD5_CTX *context,unsigned char digest[16])  
{  
    unsigned int index = 0,padlen = 0;  
    unsigned char bits[8];  
    index = (context->count[0] >> 3) & 0x3F;  
    padlen = (index < 56)?(56-index):(120-index);  
    MD5Encode(bits,context->count,8);  
    MD5Update(context,PADDING,padlen);  
    MD5Update(context,bits,8);  
    MD5Encode(digest,context->state,16);  
}  
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len)  
{  
    unsigned int i = 0,j = 0;  
    while(j < len)  
    {  
        output[j] = input[i] & 0xFF;    
        output[j+1] = (input[i] >> 8) & 0xFF;  
        output[j+2] = (input[i] >> 16) & 0xFF;  
        output[j+3] = (input[i] >> 24) & 0xFF;  
        i++;  
        j+=4;  
    }  
}  
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len)  
{  
    unsigned int i = 0,j = 0;  
    while(j < len)  
    {  
        output[i] = (input[j]) |  
            (input[j+1] << 8) |  
            (input[j+2] << 16) |  
            (input[j+3] << 24);  
        i++;  
        j+=4;   
    }  
}  
void MD5Transform(unsigned int state[4],unsigned char block[64])  
{  
    unsigned int a = state[0];  
    unsigned int b = state[1];  
    unsigned int c = state[2];  
    unsigned int d = state[3];  
    unsigned int x[64];  
    MD5Decode(x,block,64);  
    FF(a, b, c, d, x[ 0], 7, 0xd76aa478);   
    FF(d, a, b, c, x[ 1], 12, 0xe8c7b756);   
    FF(c, d, a, b, x[ 2], 17, 0x242070db);   
    FF(b, c, d, a, x[ 3], 22, 0xc1bdceee);   
    FF(a, b, c, d, x[ 4], 7, 0xf57c0faf);   
    FF(d, a, b, c, x[ 5], 12, 0x4787c62a);   
    FF(c, d, a, b, x[ 6], 17, 0xa8304613);   
    FF(b, c, d, a, x[ 7], 22, 0xfd469501);   
    FF(a, b, c, d, x[ 8], 7, 0x698098d8);   
    FF(d, a, b, c, x[ 9], 12, 0x8b44f7af);   
    FF(c, d, a, b, x[10], 17, 0xffff5bb1);   
    FF(b, c, d, a, x[11], 22, 0x895cd7be);   
    FF(a, b, c, d, x[12], 7, 0x6b901122);   
    FF(d, a, b, c, x[13], 12, 0xfd987193);   
    FF(c, d, a, b, x[14], 17, 0xa679438e);   
    FF(b, c, d, a, x[15], 22, 0x49b40821);   


    GG(a, b, c, d, x[ 1], 5, 0xf61e2562);   
    GG(d, a, b, c, x[ 6], 9, 0xc040b340);   
    GG(c, d, a, b, x[11], 14, 0x265e5a51);   
    GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);   
    GG(a, b, c, d, x[ 5], 5, 0xd62f105d);   
    GG(d, a, b, c, x[10], 9,  0x2441453);   
    GG(c, d, a, b, x[15], 14, 0xd8a1e681);   
    GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);   
    GG(a, b, c, d, x[ 9], 5, 0x21e1cde6);   
    GG(d, a, b, c, x[14], 9, 0xc33707d6);   
    GG(c, d, a, b, x[ 3], 14, 0xf4d50d87);   
    GG(b, c, d, a, x[ 8], 20, 0x455a14ed);   
    GG(a, b, c, d, x[13], 5, 0xa9e3e905);   
    GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8);   
    GG(c, d, a, b, x[ 7], 14, 0x676f02d9);   
    GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);   


    HH(a, b, c, d, x[ 5], 4, 0xfffa3942);   
    HH(d, a, b, c, x[ 8], 11, 0x8771f681);   
    HH(c, d, a, b, x[11], 16, 0x6d9d6122);   
    HH(b, c, d, a, x[14], 23, 0xfde5380c);   
    HH(a, b, c, d, x[ 1], 4, 0xa4beea44);   
    HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);   
    HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);   
    HH(b, c, d, a, x[10], 23, 0xbebfbc70);   
    HH(a, b, c, d, x[13], 4, 0x289b7ec6);   
    HH(d, a, b, c, x[ 0], 11, 0xeaa127fa);   
    HH(c, d, a, b, x[ 3], 16, 0xd4ef3085);   
    HH(b, c, d, a, x[ 6], 23,  0x4881d05);   
    HH(a, b, c, d, x[ 9], 4, 0xd9d4d039);   
    HH(d, a, b, c, x[12], 11, 0xe6db99e5);   
    HH(c, d, a, b, x[15], 16, 0x1fa27cf8);   
    HH(b, c, d, a, x[ 2], 23, 0xc4ac5665);   


    II(a, b, c, d, x[ 0], 6, 0xf4292244);   
    II(d, a, b, c, x[ 7], 10, 0x432aff97);   
    II(c, d, a, b, x[14], 15, 0xab9423a7);   
    II(b, c, d, a, x[ 5], 21, 0xfc93a039);   
    II(a, b, c, d, x[12], 6, 0x655b59c3);   
    II(d, a, b, c, x[ 3], 10, 0x8f0ccc92);   
    II(c, d, a, b, x[10], 15, 0xffeff47d);   
    II(b, c, d, a, x[ 1], 21, 0x85845dd1);   
    II(a, b, c, d, x[ 8], 6, 0x6fa87e4f);   
    II(d, a, b, c, x[15], 10, 0xfe2ce6e0);   
    II(c, d, a, b, x[ 6], 15, 0xa3014314);   
    II(b, c, d, a, x[13], 21, 0x4e0811a1);   
    II(a, b, c, d, x[ 4], 6, 0xf7537e82);   
    II(d, a, b, c, x[11], 10, 0xbd3af235);   
    II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);   
    II(b, c, d, a, x[ 9], 21, 0xeb86d391);   
    state[0] += a;  
    state[1] += b;  
    state[2] += c;  
    state[3] += d;  
}  

下面是測試程式, 主要依次呼叫MD5Init, MD5Update,MD5Final三個函式就行了

/************************************************************
Copyright (C), 2017, Leon, All Rights Reserved.
FileName: test_md5.c
Description: MD5函式測試
Author: Leon
Version: 1.0
Date: 
Function:

History:
<author>    <time>  <version>   <description>
 Leon
************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include "md5.h"

/* md5函式測試 */
int main(int argc, char *argv[])
{
    struct stat st;
    unsigned char digest[16] = {0};
    MD5_CTX context;
    int i = 0;

    if(argc < 2)
        return;

    MD5Init(&context);

    if(-1 == stat(argv[1], &st))
    {
        /* 檔案不存在則計算引數字串的MD5 */
        MD5Update(&context, argv[1], strlen(argv[1]));
    }
    else
    {
        /* 計算檔案MD5 */
        FILE *fp = fopen(argv[1], "r");
        char *data = NULL;
        int ret = 0;

        if(!fp)
        {
            perror("fopen");
            exit(-1);
        }

        data = malloc(st.st_size);
        if(!data)
        {
            perror("malloc");
            exit(-1);
        }
        ret = fread(data, 1, st.st_size, fp);
        if(ret != st.st_size)
        {
            perror("fread");
            exit(-1);
        } 
        MD5Update(&context, data, st.st_size);
        fclose(fp);
        free(data);
    }
    MD5Final(&context, digest);

    /* 列印MD5值 */
    printf("md5: ");
    for(i = 0; i < 16; i++)
    {
        printf("%02x", digest[i]);
    }
    printf("\n");
    return 0;
}

執行結果與openssl結果對比是一致的:

測試結果:
root@ubuntu:online_upgrade# ./a.out 123.txt 
md5: 86109d400f0ed29e840b47ed72777c84
root@ubuntu:online_upgrade# openssl md5 123.txt
MD5(123.txt)= 86109d400f0ed29e840b47ed72777c84

相關推薦

C語言計算檔案MD5

  計算MD5這種很標準的東西,一般直接使用別人寫好的了就行,本文主要針對寫好的介面測試一下如何使用的問題。 下面是MD5的實現 md5.h #ifndef MD5_H #define MD5_H typedef struct

C++計算檔案MD5

MD5ChecksumDefines.h //Magic initialization constants #define MD5_INIT_STATE_0 0x67452301 #define MD5_INIT_STATE_1 0xefcdab89 #define MD5

C語言計算程序中某一個函數或算法的執行時間

lock nis 程序 while tar 計算 stdio.h locks turn 計算程序中某一個函數或算法的執行時間 #include <stdio.h> #include <time.h> #include <stdlib.h>

C語言計算:t=1-1/(2*2)-1/(3*3)-...-1/(m*m)

#include <stdio.h> #include <stdlib.h> #include <math.h> int main() {     int  m,i;     int n;  

如何用C語言計算表示式的值,棧的經典應用

宣告:這個程式可以計算+,-,*,/,負數,小數 負數用括號括起來例如(-1) 負數的計算過程:(-1)  轉變為 (0-1)  哈哈~   分成六個點: 1.我的檔案結構 2.順序堆疊的標頭檔案 3.標頭

C語言(四 檔案操作、遞迴)

檔案讀寫 我們用**fopen()**來新建一個檔案或開啟一個已有的檔案. 函式原型為File *fopen(const char *filename , const char *mode) filename是檔名,mode代表訪問方式。 mode

BMP轉成C語言陣列檔案工具(用image2lcd代替bmp2h exe)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

C語言計算sinx

#include<stdio.h> #include<math.h> int jc(int n); int main() { int m=1,f=1,i=1; double sinx=0.0,x,z; double ans; scanf("%lf",&x); z

C語言計算矩陣邊緣元素之和

1 題目描述 1.1 題目描述 輸入一個整數矩陣,計算位於矩陣邊緣的元素之和。所謂矩陣邊緣的元 素,就是第一行和最後一行的元素以及第一列和最後一列的元素。 1.2 輸入要求 1.第一行為整數k,表示有k組資料。 2.每組資料由多行組成,表示一個矩陣。 3.第

C語言計算1~20的階乘之和

  昨天(2018/12/7)在做C語言的課後練習題的時候,有一道題要求我們計算1~20的階乘之和。程式碼很快就寫出來了,考慮到結果的值會比較大,而在Windows作業系統下,int 型別和 long 型別居然都是4個位元組(C#中long型別是八個位元組,找同學試了下,Linux下C語言的long型別好像也

C語言檔案操作

一、開啟檔案 1、函式 fopen(path, type) 2、引數介紹 引數 型別 說明 備註 path 字串 檔案路徑 如”./h

java c c++語言 計算階乘

import java.util.Scanner; public class C201_07_06計算階乘 { public static void main(String[] args) { Scanner scan = new Scanner(Sy

C語言檔案的輸入輸出

1.檔案標誌: D:\CC\temp\file1.dat(dat代表是資料檔案)分為三段,檔案路徑,檔名,檔案型別 2.檔案緩衝區: ANSI C標準採用緩衝檔案系統處理資料檔案 3.檔案型別指標: 緩衝檔案系統中關鍵的概念是檔案型別指標,每一個被使用的檔案都是

C語言檔案流操作的基本函式總結

#include <stdio.h> int main() { FILE* fp = fopen("data.txt","r"); if(fp == NULL) { printf("open error\n"); return -1;

C語言計算個人所得稅問題程式碼及解析

問題描述 編寫一個計算個人所得稅的程式,要求輸入收入金額後,能夠輸出應繳的個人所得稅。 個人所得稅徵收辦法如下: ◎ 起徵點為3500元; ◎ 不超過1500元的部分,徵收3%; ◎ 超過1500〜4500元的部分,徵收10%; ◎ 超過4500〜9000元的部分,徵收20%; ◎

C語言計算水分子的個數

題目: 一個水分子的質量約為,1夸脫水大約有950g,編寫一個程式,要求輸入水的夸脫數,然後顯示這麼多水中含有多少水分子。 問題分析: 從題目中可以得到1夸脫水中水分子的含量 = 1夸脫水 * 950  /  3.0e-23, 程式碼: #include &l

C++】從extern關鍵字開始談C語言檔案程式設計

extern 關鍵字 我們知道,C語言程式碼是由上到下依次執行的,不管是變數還是函式,原則上都要先定義再使用,否則就會報錯。但在實際開發中,經常會在函式或變數定義之前就使用它們,這個時候就需要提前宣告。 所謂宣告(Declaration),就是告訴編譯器我要使用這個變數或函

C語言常用檔案讀寫函式記錄

由於在vs下開發,經常使用MFC的類庫,檔案讀寫也是CFile的類級派生類,現在此記錄C語言檔案操作常用api,以備不時之需。 (1)fopen,fclose – 檔案開啟關閉函式; FILE* pFile = fopen("test.txt","w"); 第一個引數是

C語言計算多邊形

2018年11月07日 20:09:34 YeLlei 閱讀數:4 個人分類: 個人學習

C語言計算一元二次方程的根(完全版)

題目(Description): 求一元二次方程ax2+bx+c=0的根。a、b、c為任意實數。 輸入(Input): 任意三個係數a、b、c。 輸出(Output): x1 x2實根(保留2位小數),且要求x1>=x2。 說明: (1)如果a為0且b為0,則輸出 “Not an eq