訂閱
糾錯(cuò)
加入自媒體

一文告訴你C語(yǔ)言如何實(shí)現(xiàn)MD5加密

一、摘要算法

摘要算法又稱(chēng)哈希算法。

它表示輸入任意長(zhǎng)度的數(shù)據(jù),輸出固定長(zhǎng)度的數(shù)據(jù),它的主要特征是加密過(guò)程不需要密鑰,并且經(jīng)過(guò)加密的數(shù)據(jù)無(wú)法被解密。

目前可以被解密逆向的只有CRC32算法,只有輸入相同的明文數(shù)據(jù)經(jīng)過(guò)相同的消息摘要算法才能得到相同的密文。

消息摘要算法不存在密鑰的管理與分發(fā)問(wèn)題,適合于分布式網(wǎng)絡(luò)上使用。由于其加密計(jì)算的工作量相當(dāng)巨大,所以以前的這種算法通常只用于數(shù)據(jù)量有限的情況下的加密。

消息摘要算法分為三類(lèi):MD(Message Digest):消息摘要SHA(Secure Hash Algorithm):安全散列MAC(Message Authentication Code):消息認(rèn)證碼

這三類(lèi)算法的主要作用:驗(yàn)證數(shù)據(jù)的完整性

二、MD5簡(jiǎn)介

MD5即Message-Digest Algorithm 5(信息-摘要算法)。

屬于摘要算法,是一個(gè)不可逆過(guò)程,就是無(wú)論多大數(shù)據(jù),經(jīng)過(guò)算法運(yùn)算后都是生成固定長(zhǎng)度的數(shù)據(jù),結(jié)果使用16進(jìn)制進(jìn)行顯示的128bit的二進(jìn)制串。通常表示為32個(gè)十六進(jìn)制數(shù)連成的字符串。

MD5有什么用?

用于確保信息傳輸完整一致。是計(jì)算機(jī)廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語(yǔ)言普遍已有MD5實(shí)現(xiàn)。更多用在文檔校驗(yàn)上,用來(lái)生成密鑰檢測(cè)文檔是否被篡改。

三、在線MD5加密

舉例:給字符串 12334567 加密成。

如圖結(jié)果為:

32135A337F8DC8E2BB9A9B80D86BDFD0

四、C語(yǔ)言實(shí)現(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 << 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

#ifndef MD5_H

#define 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);  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加密步驟如下:

1. 定義

MD5_CTX md5c; 

2. 初始化

*******************************************************

* 名    稱(chēng): MD5Init()

* 功    能: 初始化MD5結(jié)構(gòu)體

* 入口參數(shù): 

  context:要初始化的MD5結(jié)構(gòu)體 

* 出口參數(shù): 無(wú)

********************************************************

MD5Init(MD5_CTX *context);

3. MD5值計(jì)算

實(shí)現(xiàn)MD5值的計(jì)算及結(jié)構(gòu)體的更新:

********************************************************

* 名    稱(chēng): MD5Update()

* 功    能: 將要加密的信息傳遞給初始化過(guò)的MD5結(jié)構(gòu)體,無(wú)返回值

* 入口參數(shù): 

context:初始化過(guò)了的MD5結(jié)構(gòu)體 

input:需要加密的信息,可以任意長(zhǎng)度

inputLen:指定input的長(zhǎng)度

* 出口參數(shù): 無(wú)

********************************************************

MD5Update(MD5_CTX *context,(unsigned char *)input,inputLen); 

4. 輸出轉(zhuǎn)換

********************************************************

* 名    稱(chēng): MD5Update()

* 功    能: 將加密結(jié)果存儲(chǔ)到,無(wú)返回值

* 入口參數(shù): 

 context:初始化過(guò)了的MD5結(jié)構(gòu)體 

digest :加密過(guò)的結(jié)果

* 出口參數(shù): 無(wú)

********************************************************

MD5Final(MD5_CTX *context,unsigned char digest[16]);

5. 格式整理

轉(zhuǎn)換成32位的16進(jìn)制字符串。

實(shí)例1 字符串加密

對(duì)字符串進(jìn)行加密:

1 #include

執(zhí)行結(jié)果如下:

本例對(duì)字符串12334567進(jìn)行加密,結(jié)果和在線加密結(jié)果一致。

實(shí)例2 文件加密

對(duì)文件進(jìn)行加密

#include

運(yùn)行結(jié)果:

在線驗(yàn)證結(jié)果對(duì)比:

結(jié)果

------------ END ------------

聲明: 本文由入駐維科號(hào)的作者撰寫(xiě),觀點(diǎn)僅代表作者本人,不代表OFweek立場(chǎng)。如有侵權(quán)或其他問(wèn)題,請(qǐng)聯(lián)系舉報(bào)。

發(fā)表評(píng)論

0條評(píng)論,0人參與

請(qǐng)輸入評(píng)論內(nèi)容...

請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字

您提交的評(píng)論過(guò)于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)

  • 看不清,點(diǎn)擊換一張  刷新

暫無(wú)評(píng)論

暫無(wú)評(píng)論

人工智能 獵頭職位 更多
掃碼關(guān)注公眾號(hào)
OFweek人工智能網(wǎng)
獲取更多精彩內(nèi)容
文章糾錯(cuò)
x
*文字標(biāo)題:
*糾錯(cuò)內(nèi)容:
聯(lián)系郵箱:
*驗(yàn) 證 碼:

粵公網(wǎng)安備 44030502002758號(hào)