本文詳細講解視頻已經(jīng)上傳到B站:
https://www.bilibili.com/video/BV1uy4y1p7on/
公眾號后臺回復【md5】即可獲得本文所有源碼。
一、摘要算法
摘要算法又稱哈希算法。
它表示輸入任意長度的數(shù)據(jù),輸出固定長度的數(shù)據(jù),它的主要特征是加密過程不需要密鑰,并且經(jīng)過加密的數(shù)據(jù)無法被解密。
目前可以被解密逆向的只有CRC32算法,只有輸入相同的明文數(shù)據(jù)經(jīng)過相同的消息摘要算法才能得到相同的密文。
消息摘要算法不存在密鑰的管理與分發(fā)問題,適合于分布式網(wǎng)絡(luò)上使用。由于其加密計算的工作量相當巨大,所以以前的這種算法通常只用于數(shù)據(jù)量有限的情況下的加密。
消息摘要算法分為三類:
-
MD(Message Digest):消息摘要 -
SHA(Secure Hash Algorithm):安全散列 -
MAC(Message Authentication Code):消息認證碼
這三類算法的主要作用:驗證數(shù)據(jù)的完整性
二、MD5簡介
MD5即Message-Digest Algorithm 5(信息-摘要算法)。
屬于摘要算法,是一個不可逆過程,就是無論多大數(shù)據(jù),經(jīng)過算法運算后都是生成固定長度的數(shù)據(jù),結(jié)果使用16進制進行顯示的128bit的二進制串。通常表示為32個十六進制數(shù)連成的字符串。
MD5有什么用?
用于確保信息傳輸完整一致。是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現(xiàn)。更多用在文檔校驗上,用來生成密鑰檢測文檔是否被篡改。
三、在線MD5加密
有很多在線進行MD5加密的網(wǎng)站,如下:
http://www.metools.info/code/c26.html
舉例: 給字符串?12334567?加密成。
如圖結(jié)果為:
32135A337F8DC8E2BB9A9B80D86BDFD0
四、C語言實現(xiàn)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?<>?(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?
#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?????{
?????????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??????{
???????????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);?/*?1?*/
?FF(d,?a,?b,?c,?x[?1],?12,?0xe8c7b756);?/*?2?*/
?FF(c,?d,?a,?b,?x[?2],?17,?0x242070db);?/*?3?*/
?FF(b,?c,?d,?a,?x[?3],?22,?0xc1bdceee);?/*?4?*/
?FF(a,?b,?c,?d,?x[?4],?7,?0xf57c0faf);?/*?5?*/
?FF(d,?a,?b,?c,?x[?5],?12,?0x4787c62a);?/*?6?*/
?FF(c,?d,?a,?b,?x[?6],?17,?0xa8304613);?/*?7?*/
?FF(b,?c,?d,?a,?x[?7],?22,?0xfd469501);?/*?8?*/
?FF(a,?b,?c,?d,?x[?8],?7,?0x698098d8);?/*?9?*/
?FF(d,?a,?b,?c,?x[?9],?12,?0x8b44f7af);?/*?10?*/
?FF(c,?d,?a,?b,?x[10],?17,?0xffff5bb1);?/*?11?*/
?FF(b,?c,?d,?a,?x[11],?22,?0x895cd7be);?/*?12?*/
?FF(a,?b,?c,?d,?x[12],?7,?0x6b901122);?/*?13?*/
?FF(d,?a,?b,?c,?x[13],?12,?0xfd987193);?/*?14?*/
?FF(c,?d,?a,?b,?x[14],?17,?0xa679438e);?/*?15?*/
?FF(b,?c,?d,?a,?x[15],?22,?0x49b40821);?/*?16?*/
?
?/*?Round?2?*/
?GG(a,?b,?c,?d,?x[?1],?5,?0xf61e2562);?/*?17?*/
?GG(d,?a,?b,?c,?x[?6],?9,?0xc040b340);?/*?18?*/
?GG(c,?d,?a,?b,?x[11],?14,?0x265e5a51);?/*?19?*/
?GG(b,?c,?d,?a,?x[?0],?20,?0xe9b6c7aa);?/*?20?*/
?GG(a,?b,?c,?d,?x[?5],?5,?0xd62f105d);?/*?21?*/
?GG(d,?a,?b,?c,?x[10],?9,??0x2441453);?/*?22?*/
?GG(c,?d,?a,?b,?x[15],?14,?0xd8a1e681);?/*?23?*/
?GG(b,?c,?d,?a,?x[?4],?20,?0xe7d3fbc8);?/*?24?*/
?GG(a,?b,?c,?d,?x[?9],?5,?0x21e1cde6);?/*?25?*/
?GG(d,?a,?b,?c,?x[14],?9,?0xc33707d6);?/*?26?*/
?GG(c,?d,?a,?b,?x[?3],?14,?0xf4d50d87);?/*?27?*/
?GG(b,?c,?d,?a,?x[?8],?20,?0x455a14ed);?/*?28?*/
?GG(a,?b,?c,?d,?x[13],?5,?0xa9e3e905);?/*?29?*/
?GG(d,?a,?b,?c,?x[?2],?9,?0xfcefa3f8);?/*?30?*/
?GG(c,?d,?a,?b,?x[?7],?14,?0x676f02d9);?/*?31?*/
?GG(b,?c,?d,?a,?x[12],?20,?0x8d2a4c8a);?/*?32?*/
?
?/*?Round?3?*/
?HH(a,?b,?c,?d,?x[?5],?4,?0xfffa3942);?/*?33?*/
?HH(d,?a,?b,?c,?x[?8],?11,?0x8771f681);?/*?34?*/
?HH(c,?d,?a,?b,?x[11],?16,?0x6d9d6122);?/*?35?*/
?HH(b,?c,?d,?a,?x[14],?23,?0xfde5380c);?/*?36?*/
?HH(a,?b,?c,?d,?x[?1],?4,?0xa4beea44);?/*?37?*/
?HH(d,?a,?b,?c,?x[?4],?11,?0x4bdecfa9);?/*?38?*/
?HH(c,?d,?a,?b,?x[?7],?16,?0xf6bb4b60);?/*?39?*/
?HH(b,?c,?d,?a,?x[10],?23,?0xbebfbc70);?/*?40?*/
?HH(a,?b,?c,?d,?x[13],?4,?0x289b7ec6);?/*?41?*/
?HH(d,?a,?b,?c,?x[?0],?11,?0xeaa127fa);?/*?42?*/
?HH(c,?d,?a,?b,?x[?3],?16,?0xd4ef3085);?/*?43?*/
?HH(b,?c,?d,?a,?x[?6],?23,??0x4881d05);?/*?44?*/
?HH(a,?b,?c,?d,?x[?9],?4,?0xd9d4d039);?/*?45?*/
?HH(d,?a,?b,?c,?x[12],?11,?0xe6db99e5);?/*?46?*/
?HH(c,?d,?a,?b,?x[15],?16,?0x1fa27cf8);?/*?47?*/
?HH(b,?c,?d,?a,?x[?2],?23,?0xc4ac5665);?/*?48?*/
?
?/*?Round?4?*/
?II(a,?b,?c,?d,?x[?0],?6,?0xf4292244);?/*?49?*/
?II(d,?a,?b,?c,?x[?7],?10,?0x432aff97);?/*?50?*/
?II(c,?d,?a,?b,?x[14],?15,?0xab9423a7);?/*?51?*/
?II(b,?c,?d,?a,?x[?5],?21,?0xfc93a039);?/*?52?*/
?II(a,?b,?c,?d,?x[12],?6,?0x655b59c3);?/*?53?*/
?II(d,?a,?b,?c,?x[?3],?10,?0x8f0ccc92);?/*?54?*/
?II(c,?d,?a,?b,?x[10],?15,?0xffeff47d);?/*?55?*/
?II(b,?c,?d,?a,?x[?1],?21,?0x85845dd1);?/*?56?*/
?II(a,?b,?c,?d,?x[?8],?6,?0x6fa87e4f);?/*?57?*/
?II(d,?a,?b,?c,?x[15],?10,?0xfe2ce6e0);?/*?58?*/
?II(c,?d,?a,?b,?x[?6],?15,?0xa3014314);?/*?59?*/
?II(b,?c,?d,?a,?x[13],?21,?0x4e0811a1);?/*?60?*/
?II(a,?b,?c,?d,?x[?4],?6,?0xf7537e82);?/*?61?*/
?II(d,?a,?b,?c,?x[11],?10,?0xbd3af235);?/*?62?*/
?II(c,?d,?a,?b,?x[?2],?15,?0x2ad7d2bb);?/*?63?*/
?II(b,?c,?d,?a,?x[?9],?21,?0xeb86d391);?/*?64?*/
?????state[0]?+=?a;
?????state[1]?+=?b;
?????state[2]?+=?c;
?????state[3]?+=?d;
}
五、MD5加密實例
MD5加密步驟如下:
-
定義
MD5_CTX?md5c;?
-
初始化
/********************************************************
*?名????稱:?MD5Init()
*?功????能:?初始化MD5結(jié)構(gòu)體
*?入口參數(shù):?
?? context:要初始化的MD5結(jié)構(gòu)體?
*?出口參數(shù):?無
*********************************************************/
MD5Init(MD5_CTX?*context);
-
MD5值計算
實現(xiàn)MD5值的計算及結(jié)構(gòu)體的更新:
/*********************************************************
*?名????稱:?MD5Update()
*?功????能:?將要加密的信息傳遞給初始化過的MD5結(jié)構(gòu)體,無返回值
*?入口參數(shù):?
?? context:初始化過了的MD5結(jié)構(gòu)體?
??? input:需要加密的信息,可以任意長度
??? inputLen:指定input的長度
*?出口參數(shù):?無
*********************************************************/
MD5Update(MD5_CTX?*context,(unsigned?char?*)input,inputLen);?
-
輸出轉(zhuǎn)換
/*********************************************************
*?名????稱:?MD5Update()
*?功????能:?將加密結(jié)果存儲到,無返回值
*?入口參數(shù):?
?? context:初始化過了的MD5結(jié)構(gòu)體?
??? digest :加密過的結(jié)果
*?出口參數(shù):?無
*********************************************************/
MD5Final(MD5_CTX?*context,unsigned?char?digest[16]);
-
格式整理
轉(zhuǎn)換成32位的16進制字符串。
實例1 字符串加密
對字符串進行加密:
??1?#include?
??2?#include?
??3?#include?"md5.h"
??4?#include?
??5?#include?
??6?#include?
??7?#include?
??8?
??9?void?main(?void?)?
?10?{?
?11?????int?read_len;
?12?????int?i?;
?13?????char?temp[8]={0};
?14?????unsigned?char?digest[16];?//存放結(jié)果?
?15?????char?hexbuf[128]="12334567";
?16?????unsigned?char?decrypt[16]={0};??
?17?????unsigned?char?decrypt32[64]={0};????
?18?
?19?????MD5_CTX?md5c;?
?20?
?21?????MD5Init(&md5c);?//初始化
?22?????read_len?=?strlen(hexbuf);
?23?????MD5Update(&md5c,(unsigned?char?*)hexbuf,read_len);??
?24?
?25?????MD5Final(&md5c,decrypt);?
?26?????strcpy((char?*)decrypt32,"");
?27?
?28?????for(i=0;i<16;i++)
?29?????{
?30?????????sprintf(temp,"%02x",decrypt[i]);
?31?????????strcat((char?*)decrypt32,temp);
?32?????}
?33?????printf("md5:%s\n",decrypt32);
?34?????
?35?????return;
?36?}
執(zhí)行結(jié)果如下:
本例對字符串12334567進行加密,結(jié)果和在線加密結(jié)果一致。
實例2 文件加密
對文件進行加密
#include?
#include?
#include?"md5.h"
#include?
#include?
#include?
#include?
#define?FORWORD_FW?"123.c"
int?calc_md5(char*filename,char*dest)
{
?int?i;
?int?filelen?=?0;
?int?read_len;
?char?temp[8]={0};?
?char?hexbuf[128]={0};
?unsigned?char?decrypt[16]={0};??
?unsigned?char?decrypt32[64]={0};
?MD5_CTX?md5;
?char?fw_path[128];
?int?fdf;
?
?fdf?=?open(filename,O_RDWR);
?if(fdf<0)
?{
??printf("%s?not?exist\n",FORWORD_FW);
??return?-1;
?}
?
?MD5Init(&md5);??
?while(1)
?{
??read_len?=?read(fdf,?hexbuf,sizeof(hexbuf));?
??if?(read_len?<0)?{??
???close(fdf);???
???return?-1;
??}
??if(read_len==0)
??{
???break;
??}
??filelen?+=?read_len;
??MD5Update(&md5,(unsigned?char?*)hexbuf,read_len);?
?}
?
?MD5Final(&md5,decrypt);?
?strcpy((char?*)decrypt32,"");
?
?for(i=0;i<16;i++)
?{
??sprintf(temp,"%02x",decrypt[i]);
??strcat((char?*)decrypt32,temp);
?}
?strcpy(dest,decrypt32);
?printf("md5:%s?len=%d\n",dest,filelen);
?close(fdf);
?return?filelen;
}
int?main(int?argc,?char?*argv[])
{
?int?ret;
?int?filelen;
?char?md5_str[64]={0};
?char?cmd[256]={0};
?
?filelen?=?calc_md5(FORWORD_FW,md5_str);
?if(filelen<0)
?{
??printf("calc_md5?fail\n");
??return?-1;
?}
?return?0;
}
運行結(jié)果:
在線驗證結(jié)果對比:
http://www.metools.info/other/o21.html
免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!