md5源码(c++)

/* myMD5.h
 * time : Asg 5th,2011
 * author : BoJing .Wang
 * email : [email protected]
 */

#ifndef MYMD5_H
#define MYMD5_H

#include <string>
#include <fstream>

typedef unsigned char byte;
typedef unsigned int uint32;

using std::string;
using std::ifstream;

class MD5 {
public:
    /*constructor */
    MD5();
    MD5(const void * input,size_t length);
    MD5(const string & str);
    MD5(ifstream & in);

    void update(const void * input,size_t length);
    void update(const string &str);
    void update(ifstream & in);

    const byte * digest();
    string toString();
    void reset();

private:
    /*copy constructor */
    MD5(const MD5 &);
    MD5 operator = (const MD5&);
    
    void update(const byte * input,size_t length);
    void final();
    void transform(const byte block[64]);
    void encode(const uint32 * input,byte * output,size_t length);
    void decode(const byte * input,uint32 * output,size_t length);
    string bytesToHexString(const byte * input,size_t length);

private:
    uint32 _state[4];
    uint32 _count[2];
    byte _buffer[64];
    byte _digest[16];
    bool _finished;
    static const byte PADDING[64];
    static const char HEX[16];
    enum { BUFFER_SIZE = 1024 };
};
#endif


/* myMD5.cc
 * time : Asg 5th,2011
 * author : BoJing .Wang
 * email : [email protected]
 */


#include "myMD5.h"
#include <iostream>
#include <cstring>

using namespace std;


/* F,G,H and I are basic MD5 function */
#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))))
/* FF(a,b,c,d,Mj,s,ti)表示 a=b+((a+(F(b,c,d)+Mj+ti))<<s) */
#define FF(a,b,c,d,Mj,s,ti) do{              \
    a += (F(b,c,d)+Mj+ti);                    \
    ROTATE_LEFT(a,s);                        \
    a += b;                                    \
}while(0)

/* GG(a,b,c,d,Mj,s,ti)表示 a=b+((a+(G(b,c,d)+Mj+ti))<<s)  */

#define GG(a,b,c,d,Mj,s,ti) do{               \
    a += (H(b,c,d)+Mj+ti);                    \
    ROTATE_LEFT(a,s);                        \
    a += b;                                    \
}while(0)

/* HH(a,b,c,d,Mj,s,ti)表示 a=b+((a+(H(b,c,d)+Mj+ti))<<s)*/
#define HH(a,b,c,d,Mj,s,ti) do{              \
    a += (H(b,c,d)+Mj+ti);                    \
    ROTATE_LEFT(a,s);                        \
    a += b;                                    \
}while(0)

/* II(a,b,c,d,Mj,s,ti)表示 a=b+((a+(I(b,c,d)+Mj+ti))<<s)  */
#define II(a,b,c,d,Mj,s,ti) do{              \
    a += (I(b,c,d)+Mj+ti);                    \
    ROTATE_LEFT(a,s);                        \
    a += b;                                    \
}while(0)


const byte MD5::PADDING[64] ={ 0x80 };
const char MD5::HEX[16] = {
    '0','1','2','3',
    '4','5','6','7',
    '8','9','a','b',
    'c','d','e','f'
};

/* method for MD5 */

MD5::MD5(){
    reset();
}

MD5::MD5(const void* input, size_t length){
    reset();
    update(input,length);
}

MD5::MD5(const string & str){
    reset();
    update(str);
}

MD5::MD5(ifstream & in){
    reset();
    update(in);
}

void MD5::update(const void* input, size_t length){
    update((const byte *)input,length);
}

void MD5::update(const string& str){
    update((const byte *)str.c_str(),str.length());
}

void MD5::update(ifstream & in){
    if(!in)
        return ;
    
    std::streamsize length;
    char buffer[BUFFER_SIZE];

    while(!in.eof()){
        in.read(buffer,BUFFER_SIZE);
        length = in.gcount();
        
        if(length > 0){
            update(buffer,length);
        }
    }
    in.close();
}

void MD5::reset(){
    _finished = false;
    _count[0] = _count[1] = 0;
    _state[0] = 0x01234567;
    _state[1] = 0x89abcdef;
    _state[2] = 0xfedcba89;
    _state[3] = 0x76543210;
}

void MD5::update(const byte* input, size_t length){
    uint32 i,index,partLen;

    _finished = false;
    index = (uint32)((_count[0] >> 3) & 0x3f);
    if((_count[0] += ((uint32)length << 3)) < ((uint32)length << 3)){
        _count[1] ++;
    }
    
    _count[1] += ((uint32)length >> 29);
    partLen = 64 - index;
    
    if(length >= partLen){
        memcpy(&_buffer[index],input,partLen);
        transform(_buffer);

        for(i = partLen;i+63 < length;i += 64){
            transform(&input[i]);
        }
        index = 0;
    }else{
        i = 0;
    }
}

void MD5::transform(const byte block[64]){
    uint32 a = _state[0], b = _state[1],c = _state[2],d = _state[3],x[16];
    decode(block,x,16);

    /* Round 1 */
    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);
    /* Round 2 */
    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,0x02441453);
    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);
    /* Round 3 */
    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,0x04881d05);
    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);
    /* Round 4 */
    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;

}

void MD5::encode(const uint32 * input,byte * output,size_t length){
    for(size_t i = 0,j = 0;j < length;i ++,j += 4){
        output[j] = (byte)(input[i] & 0xff);
        output[j + 1] = (byte)((input[i] >> 8) & 0xff);
        output[j + 2] = (byte)((input[i] >> 16) & 0xff);
        output[j + 3] = (byte)((input[i] >> 24) & 0xff);
    }
}

void MD5::decode(const byte * input,uint32 * output,size_t length){
    for(size_t i = 0,j = 0;j < length;i ++,j += 4){
        output[i] = ((uint32)input[j]) | ((uint32)input[j+1]) |
                ((uint32)input[j+2]) | ((uint32)input[j+3]);
    }
}

string MD5::bytesToHexString(const byte * input,size_t length){
    string str;

    str.reserve(length << 1);
    for(int i = 0;i < length;i ++){
        int t = input[i];
        int a = t / 16;
        int b = t % 16;
        
        str.append(1,HEX[a]);
        str.append(1,HEX[b]);
    }
    return str;
}

string MD5::toString(){
    return bytesToHexString(digest(),16);
}

const byte * MD5::digest(){
    if(!_finished){
        _finished = true;
        final();
    }
    return _digest;
}

void MD5::final(){
    byte bits[8];
    uint32 oldState[4];
    uint32 oldCount[2];
    uint32 index,padLen;

    memcpy(oldState,_state,16);
    memcpy(oldCount,_count,16);

    encode(_count,bits,8);
    index = (uint32)((_count[0] >> 3) & 0x3f);
    padLen = (index < 56)?(56 - index) : (120 - index);
    update(PADDING,padLen);

    update(bits,8);
    encode(_state,_digest,16);
    memcpy(_state,oldState,16);
    memcpy(_count,oldCount,8);
}


/* myMD5IO.h
 * time : Asg 5th,2011
 * author : BoJing .Wang
 * email : [email protected]
 */


#ifndef MYMD5IO_H
#define MYMD5IO_H

#include <iostream>
#include <fstream>
#include "myMD5.h"

using namespace std;


void PrintMD5(const string& str, MD5& md5);
string FileDigest(const string& file);

#endif


/* myMD5IO.cc
 * time : Asg 5th,2011
 * author : BoJing .Wang
 * email : [email protected]
 */


#include "myMD5IO.h"

using namespace std;


void PrintMD5(const string& str, MD5& md5) {
    cout << "MD5(\"" << str << "\") = " << md5.toString() << endl;
}
string FileDigest(const string& file) {
    ifstream in(file.c_str(), ios::binary);
    if (!in) {
        return "";
    }
    
    MD5 md5;
    std::streamsize length;
    char buffer[1024];
    
    while (!in.eof()) {
        in.read(buffer, 1024);
        length = in.gcount();
        if (length > 0) {
            md5.update(buffer, length);
        }
    }
    in.close();
    return md5.toString();
}

参考资料:

《The MD5 Message-Digest Algorithm》:http://www.ietf.org/rfc/rfc1321.txt

MD5加密算法原理 》:http://mcm.csu.edu.cn/Forums/1235/ShowPost.aspx

MD5算法研究》:http://www.blogjava.net/songfei/articles/17601.html

《MD5算法》:http://baike.baidu.com/view/706946.htm

你可能感兴趣的:(MD5)