zoukankan      html  css  js  c++  java
  • MD5 算法实现(c++)

    用c++实现了md5算法。包含 md5.h 和md5.cpp 两个文件。

    主要参考百度百科 “MD5” 原理的描述:http://baike.baidu.cn/view/7636.htm,代码中变量命名也是参考其中的公式,程序的使用说明在md5.h 文件的末尾注释中。

    测试结果和百度百科测试例子一致。

    实现过程中需要注意事项:最后把四个变量A B C D 链接成结果时 ,注意变量高低位的先后顺序,具体参考 LinkResult()方法。

    md5.h

     1 #ifndef _MD5_H_
     2 #define _MD5_H_
     3 
     4 #include <iostream>
     5 #include <string>
     6 using namespace std;
     7 
     8 class MD5
     9 {
    10     public:
    11         typedef unsigned char uchar8; //make sure it is 8bit
    12         typedef char char8; //make sure it is 8bit
    13         MD5();
    14         
    15         void init();
    16 
    17         void UpdateMd5(const uchar8 input[], const int length);      
    18         void UpdateMd5(const char8 input[], const int length);     
    19         
    20         void Finalize();
    21         
    22         void ComputMd5(const uchar8 input[], const int length); 
    23         void ComputMd5(const char8 input[], const int length); 
    24         
    25         string GetMd5();
    26         
    27         void printMd5();
    28         
    29         
    30     private:
    31         typedef unsigned int uint32;       //make sure it is 32 bit;
    32         typedef unsigned long long uint64; //make sure it is 64 bit;
    33         uint32 A, B, C, D;
    34         const static int blockLen_ = 64;    // 512/8                                  
    35         //the remain after last updata (because md5 may be computed segment by segment)
    36         uchar8 remain_[blockLen_];                    
    37         int remainNum_ ;         // the number of remain_,  < 64 
    38         uint64 totalInputBits_;
    39         uchar8 md5Result_[16];   //bit style md5 result,totally 128 bit
    40         char md5Result_hex_[33]; //hexadecimal style result; md5Result_hex_[32]='\0'
    41         bool isDone_;            // indicate the comput is finished;
    42                    
    43         inline uint32 RotateLeft(const uint32 x, int n);
    44         inline uint32 F(const uint32 x, const uint32 y, const uint32 z);
    45         inline uint32 G(const uint32 x, const uint32 y, const uint32 z);
    46         inline uint32 H(const uint32 x, const uint32 y, const uint32 z);
    47         inline uint32 I(const uint32 x, const uint32 y, const uint32 z);
    48         inline void FF(uint32 &a, const uint32 b, const uint32 c, const uint32 d,
    49                        const uint32 Mj, const int s, const uint32 ti);
    50         inline void GG(uint32 &a, const uint32 b, const uint32 c, const uint32 d,
    51                        const uint32 Mj, const int s, const uint32 ti);
    52         inline void HH(uint32 &a, const uint32 b, const uint32 c, const uint32 d,
    53                        const uint32 Mj, const int s, const uint32 ti);
    54         inline void II(uint32 &a, const uint32 b, const uint32 c, const uint32 d,
    55                        const uint32 Mj, const int s, const uint32 ti);
    56                        
    57 
    58         void UcharToUint(uint32 output[], const uchar8 input[], const unsigned int transLength);
    59         
    60         void FourRound(const uchar8 block[]);    
    61 
    62         void LinkResult();
    63                     
    64 };
    65 
    66 /* user guide
    67    you can comput the md5 by using the funtion ComputMd5
    68    eg:
    69        MD5 m;
    70        MD5::char8 str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    71        m.ComputMd5(str,sizeof(str) - 1);   
    72        m.printMd5();
    73 
    74     if you want to comput segment by segment,you can do as follow, and init() is suggested 
    75     the begging,and Finalize() must call in the end:
    76         
    77         MD5 M;
    78         m.init();
    79         MD5::uchar8 str1[] = "ABCDEFGHIJKLMN";
    80         MD5::uchar8 str2[] = "OPQRSTUVWXYZabcdefghijk";
    81         MD5::uchar8 str3[] = "lmnopqrstuvwxyz";
    82         m.UpdateMd5(str1,sizeof(str1) - 1);
    83         m.UpdateMd5(str2,sizeof(str2) - 1);
    84         m.UpdateMd5(str3,sizeof(str3) - 1);
    85         m.Finalize();
    86         m.printMd5();
    87 
    88     if you want to comput the md5 of a file, you can use the interface of this program.
    89 */
    90 
    91 #endif
    View Code

    md5.cpp

      1 #include"md5.h"
      2 
      3 #include<iostream>
      4 using namespace std;
      5 
      6 const int S[4][4] = {7, 12, 17, 22,
      7                      5, 9, 14, 20,
      8                      4, 11, 16, 23,
      9                      6, 10, 15, 21};
     10 void MD5::init()
     11 {
     12     A = 0x67452301;
     13     B = 0xefcdab89;
     14     C = 0x98badcfe;
     15     D = 0x10325476;
     16     remainNum_ = 0;
     17     remain_[0] = '\0';
     18     md5Result_hex_[0] = '\0';
     19     md5Result_[0] = '\0';
     20     totalInputBits_ = 0;
     21     isDone_ = false;
     22 }
     23 
     24 MD5::MD5()
     25 {
     26     init();
     27 }
     28 
     29 inline MD5::uint32 MD5::RotateLeft(const uint32 x, int n)
     30 {
     31     return (x << n) | (x >> (32-n));        
     32     // if x is signed, use: (x << n) | ((x & 0xFFFFFFFF) >> (32-n))
     33 }
     34 inline MD5::uint32 MD5::F(const uint32 x, const uint32 y, const uint32 z)
     35 {
     36     return (x & y) | ((~x) & z);
     37 }
     38 inline MD5::uint32 MD5::G(const uint32 x, const uint32 y, const uint32 z)
     39 {
     40     return (x & z) | (y & (~z));
     41 }
     42 inline MD5::uint32 MD5::H(const uint32 x, const uint32 y, const uint32 z)
     43 {
     44     return x ^ y ^ z;
     45 }
     46 inline MD5::uint32 MD5::I(const uint32 x, const uint32 y, const uint32 z)
     47 {
     48     return y ^ (x | (~z));
     49 }
     50 
     51 inline void MD5::FF(uint32 &a, const uint32 b, const uint32 c, const uint32 d,
     52                     const uint32 Mj, const int s, const uint32 ti)
     53 {
     54     a = b + RotateLeft(a + F(b, c, d) + Mj + ti, s);
     55 }      
     56 inline void MD5::GG(uint32 &a, const uint32 b, const uint32 c, const uint32 d,
     57                     const uint32 Mj, const int s, const uint32 ti)
     58 {
     59     a = b + RotateLeft(a + G(b, c, d) + Mj + ti, s);
     60 }                   
     61 inline void MD5::HH(uint32 &a, const uint32 b, const uint32 c, const uint32 d,
     62                     const uint32 Mj, const int s, const uint32 ti)
     63 {
     64     a = b + RotateLeft(a + H(b, c, d) + Mj + ti, s);
     65 }                    
     66 inline void MD5::II(uint32 &a, const uint32 b, const uint32 c, const uint32 d,
     67                     const uint32 Mj, const int s, const uint32 ti)
     68 {
     69     a = b + RotateLeft(a + I(b, c, d) + Mj + ti, s);
     70 }          
     71 
     72 // link A B C D to result(bit style result and hexadecimal style result)
     73 void MD5::LinkResult()
     74 {
     75     //bit style result
     76     for(int i = 0; i < 4; i++)  //link A: low to high
     77     {
     78         md5Result_[i] = (A >> 8*i) & 0xff;
     79     }
     80     for(int i = 4; i<8; i++)   //link B: low to high
     81     {
     82         md5Result_[i] = (B >> 8*(i - 4)) & 0xff;
     83     }
     84     for(int i = 8; i<12; i++)  //link C: low to high
     85     {
     86         md5Result_[i] = (C >> 8*(i - 8)) & 0xff;
     87     }
     88     for(int i = 12; i<16; i++)  //link D: low to high
     89     {
     90         md5Result_[i] = (D >> 8*(i - 12)) & 0xff;
     91     }
     92 
     93     //change to hexadecimal style result
     94     // note: it is not the same as simply link hex(A) hex(B) hex(C) hex(D)
     95     for(int i = 0; i < 16; i++)
     96         sprintf(& md5Result_hex_[i*2], "%02x", md5Result_[i]);
     97     md5Result_hex_[32] = '\0';
     98 
     99 }
    100 
    101 //print the md5 by hex
    102 void MD5::printMd5()
    103 {
    104     if(!isDone_)
    105     {
    106         cout<< "Error: computation is not finished" <<endl;
    107         
    108     }
    109     else
    110         cout<< "MD5 Value: " << md5Result_hex_ <<endl;
    111 }
    112 
    113 //get the md5 value of hex style 
    114 string MD5::GetMd5()
    115 {
    116     if(!isDone_)
    117     {
    118         cout<< "Error: computation is not finished" <<endl;
    119         exit(0);
    120     }
    121     string a((const char *)md5Result_hex_);
    122     return a;
    123 }
    124 
    125 void MD5::UcharToUint(uint32 output[], const uchar8 input[], const unsigned int transLength)         
    126 {
    127     for(int i = 0, j = 0; j < transLength; i++, j += 4)
    128     {
    129         output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) |
    130                 (((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24);
    131     }
    132 }
    133 
    134 // four round on a block of 512 bits;
    135 void MD5::FourRound(const uchar8 block[])
    136 {
    137     uint32 a = A, b = B, c = C, d = D;
    138     uint32 M[16];
    139     UcharToUint(M, block, blockLen_); //blockLen_ is a const int =64;
    140     
    141     //round 1
    142     FF (a, b, c, d, M[ 0], S[0][0], 0xd76aa478); 
    143     FF (d, a, b, c, M[ 1], S[0][1], 0xe8c7b756); 
    144     FF (c, d, a, b, M[ 2], S[0][2], 0x242070db); 
    145     FF (b, c, d, a, M[ 3], S[0][3], 0xc1bdceee); 
    146     FF (a, b, c, d, M[ 4], S[0][0], 0xf57c0faf); 
    147     FF (d, a, b, c, M[ 5], S[0][1], 0x4787c62a); 
    148     FF (c, d, a, b, M[ 6], S[0][2], 0xa8304613);
    149     FF (b, c, d, a, M[ 7], S[0][3], 0xfd469501);
    150     FF (a, b, c, d, M[ 8], S[0][0], 0x698098d8); 
    151     FF (d, a, b, c, M[ 9], S[0][1], 0x8b44f7af);
    152     FF (c, d, a, b, M[10], S[0][2], 0xffff5bb1); 
    153     FF (b, c, d, a, M[11], S[0][3], 0x895cd7be); 
    154     FF (a, b, c, d, M[12], S[0][0], 0x6b901122);
    155     FF (d, a, b, c, M[13], S[0][1], 0xfd987193);
    156     FF (c, d, a, b, M[14], S[0][2], 0xa679438e);
    157     FF (b, c, d, a, M[15], S[0][3], 0x49b40821); 
    158 
    159     // round 2 
    160     GG (a, b, c, d, M[ 1], S[1][0], 0xf61e2562); 
    161     GG (d, a, b, c, M[ 6], S[1][1], 0xc040b340); 
    162     GG (c, d, a, b, M[11], S[1][2], 0x265e5a51); 
    163     GG (b, c, d, a, M[ 0], S[1][3], 0xe9b6c7aa);
    164     GG (a, b, c, d, M[ 5], S[1][0], 0xd62f105d); 
    165     GG (d, a, b, c, M[10], S[1][1],  0x2441453); 
    166     GG (c, d, a, b, M[15], S[1][2], 0xd8a1e681);
    167     GG (b, c, d, a, M[ 4], S[1][3], 0xe7d3fbc8); 
    168     GG (a, b, c, d, M[ 9], S[1][0], 0x21e1cde6);
    169     GG (d, a, b, c, M[14], S[1][1], 0xc33707d6);
    170     GG (c, d, a, b, M[ 3], S[1][2], 0xf4d50d87);
    171     GG (b, c, d, a, M[ 8], S[1][3], 0x455a14ed); 
    172     GG (a, b, c, d, M[13], S[1][0], 0xa9e3e905); 
    173     GG (d, a, b, c, M[ 2], S[1][1], 0xfcefa3f8); 
    174     GG (c, d, a, b, M[ 7], S[1][2], 0x676f02d9);
    175     GG (b, c, d, a, M[12], S[1][3], 0x8d2a4c8a);
    176 
    177     //round 3 
    178     HH (a, b, c, d, M[ 5], S[2][0], 0xfffa3942); 
    179     HH (d, a, b, c, M[ 8], S[2][1], 0x8771f681); 
    180     HH (c, d, a, b, M[11], S[2][2], 0x6d9d6122); 
    181     HH (b, c, d, a, M[14], S[2][3], 0xfde5380c);
    182     HH (a, b, c, d, M[ 1], S[2][0], 0xa4beea44); 
    183     HH (d, a, b, c, M[ 4], S[2][1], 0x4bdecfa9);
    184     HH (c, d, a, b, M[ 7], S[2][2], 0xf6bb4b60); 
    185     HH (b, c, d, a, M[10], S[2][3], 0xbebfbc70); 
    186     HH (a, b, c, d, M[13], S[2][0], 0x289b7ec6); 
    187     HH (d, a, b, c, M[ 0], S[2][1], 0xeaa127fa); 
    188     HH (c, d, a, b, M[ 3], S[2][2], 0xd4ef3085);
    189     HH (b, c, d, a, M[ 6], S[2][3],  0x4881d05); 
    190     HH (a, b, c, d, M[ 9], S[2][0], 0xd9d4d039); 
    191     HH (d, a, b, c, M[12], S[2][1], 0xe6db99e5); 
    192     HH (c, d, a, b, M[15], S[2][2], 0x1fa27cf8); 
    193     HH (b, c, d, a, M[ 2], S[2][3], 0xc4ac5665); 
    194   
    195     //round 4 
    196     II (a, b, c, d, M[ 0], S[3][0], 0xf4292244); 
    197     II (d, a, b, c, M[ 7], S[3][1], 0x432aff97); 
    198     II (c, d, a, b, M[14], S[3][2], 0xab9423a7); 
    199     II (b, c, d, a, M[ 5], S[3][3], 0xfc93a039);
    200     II (a, b, c, d, M[12], S[3][0], 0x655b59c3); 
    201     II (d, a, b, c, M[ 3], S[3][1], 0x8f0ccc92); 
    202     II (c, d, a, b, M[10], S[3][2], 0xffeff47d); 
    203     II (b, c, d, a, M[ 1], S[3][3], 0x85845dd1); 
    204     II (a, b, c, d, M[ 8], S[3][0], 0x6fa87e4f); 
    205     II (d, a, b, c, M[15], S[3][1], 0xfe2ce6e0); 
    206     II (c, d, a, b, M[ 6], S[3][2], 0xa3014314); 
    207     II (b, c, d, a, M[13], S[3][3], 0x4e0811a1); 
    208     II (a, b, c, d, M[ 4], S[3][0], 0xf7537e82); 
    209     II (d, a, b, c, M[11], S[3][1], 0xbd3af235); 
    210     II (c, d, a, b, M[ 2], S[3][2], 0x2ad7d2bb);
    211     II (b, c, d, a, M[ 9], S[3][3], 0xeb86d391); 
    212   
    213     A += a;
    214     B += b;
    215     C += c;
    216     D += d;
    217 }
    218 
    219 // update md5,must consider the remain_.
    220 void MD5::UpdateMd5(const uchar8 input[], const int length)
    221 {    
    222     isDone_ = false;
    223     totalInputBits_ += (length << 3);
    224     
    225     int start = blockLen_ - remainNum_; //blockLen_ = 64
    226     //copy a part of input to remain_ so it can form a block(size=64)
    227   
    228     if(start <= length)
    229     {
    230         // can form a block,then do FourRound to this block
    231             memcpy(&remain_[remainNum_], input, start) ;
    232             FourRound(remain_);
    233 
    234             int i;
    235             for(i = start; i <= length - blockLen_; i += blockLen_)
    236             {
    237                 FourRound(&input[i]);
    238             }
    239             remainNum_ = length - i;  
    240             memcpy(remain_, &input[i], remainNum_);  
    241     }     
    242     else
    243     {
    244         // can not form a block, function return;
    245         memcpy(&remain_[remainNum_], input, length);
    246         remainNum_ += length;
    247     }    
    248     
    249 }
    250 
    251 void MD5::UpdateMd5(const char8 input[], const int length)
    252 {
    253     UpdateMd5((const uchar8 *)input, length);
    254 }
    255 
    256 // padding with 100000... to remain_ and add the 64bit original size of input 
    257 void MD5::Finalize()
    258 {
    259     if(isDone_ == true)
    260         return;
    261         
    262     uchar8 padding[64] = {
    263     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    264     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    265     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    266     };
    267  
    268     int temp = 56 - remainNum_;  //56 = 448/8
    269     if(temp > 0)
    270     {
    271         UpdateMd5(padding, temp);
    272         totalInputBits_ -= (temp << 3);
    273     }
    274     else if(temp < 0)
    275     {
    276         UpdateMd5(padding, 64 + temp);
    277         totalInputBits_ -= ((64 + temp) << 3);
    278     }
    279  
    280     // trans totalInputBits_ to uchar8 (64bits)
    281     uchar8 Bits[8];
    282     for(int i = 0; i < 8; i++)
    283     {
    284         Bits[i] = (totalInputBits_ >> 8*i) & 0xff;
    285     }
    286     
    287     UpdateMd5(Bits, 8); // add the number of  original input (the last 64bits)
    288     
    289     LinkResult();
    290     isDone_ = true;
    291 }
    292 
    293 // comput the md5 based on input, (just this one input)
    294 void MD5::ComputMd5(const uchar8 input[], const int length)
    295 {
    296     init();
    297     UpdateMd5(input, length);
    298     Finalize();
    299 }
    300 
    301 void MD5::ComputMd5(const char8 input[], const int length)
    302 {
    303     ComputMd5((const uchar8 *)input, length);
    304 }
    View Code

     【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/archive/2013/06/02/3114056.html

  • 相关阅读:
    FireGestures 火狐手势插件 使用
    计算分段采样区间中的平均值,标准差,中位数,积分值等的类
    DWR与Spring结合
    项目总结
    在线机器学习算法及其伪代码
    Hdu 1394 Minimum Inversion Number、Poj 2299 UltraQuickSort
    Ubuntn 安装sendmail并把硬盘空间信息发送到指定邮箱
    iPhone应用程序开发使用Core Data (一)
    [置顶] C++里被人遗忘的智能指针
    HTML标签p和div的不同
  • 原文地址:https://www.cnblogs.com/TenosDoIt/p/3114056.html
Copyright © 2011-2022 走看看