/* 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