#ant

The dreams in which I'm dying are the best I've ever had...

MD5算法的C++实现

1. Introduction
MD5算法是一种消息摘要算法(Message Digest Algorithm),此算法以任意长度的信息(message)作为输入进行计算,产生一个128-bit(16-byte)的指纹或报文摘要(fingerprint or message digest)。两个不同的message产生相同message digest的几率相当小,从一个给定的message digest逆向产生原始message更是困难(不过据说我国的某个教授很善于从message digest构造message),因此MD5算法适合用在数字签名应用中。MD5实现简单,在32位的机器上运行速度也相当快,当然实际应用也不仅仅局限于数字签名。

2. MD5 Algorithm Description
假设输入信息(input message)的长度为b(bit),我们想要产生它的报文摘要,在此处b为任意的非负整数:b也可能为0,也不一定为8的整数倍,且可能是任意大的长度。设该信息的比特流表示如下:

          M[0] M[1] M[2] ... M[b-1]

计算此信息的报文摘要需要如下5步:
2.1 Append Padding Bits
信息计算前先要进行位补位,设补位后信息的长度为LEN(bit),则LEN%512 = 448(bit),即数据扩展至
K*512+448(bit)。即K*64+56(byte),K为整数。补位操作始终要执行,即使补位前信息的长度对512求余的结果是448。具体补位操作:补一个1,然后补0至满足上述要求。总共最少要补1bit,最多补512bit。

2.2 Append Length
将输入信息的原始长度b(bit)表示成一个64-bit的数字,把它添加到上一步的结果后面(在32位的机器上,这64位将用2个字来表示并且低位在前)。当遇到b大于2^64这种极少的情况时,b的高位被截去,仅使用b的低64位。经过上面两步,数据就被填补成长度为512(bit)的倍数。也就是说,此时的数据长度是16个字(32byte)的整数倍。此时的数据表示为:

          M[0 ... N-1]

其中的N是16的倍数。

2.3 Initialize MD Buffer
用一个四个字的缓冲器(A,B,C,D)来计算报文摘要,A,B,C,D分别是32位的寄存器,初始化使用的是十六进制表示的数字,注意低字节在前:

        word A: 01 23 45 67
        word B: 89 ab cd ef
        word C: fe dc ba 98
        word D: 76 54 32 10


2.4 Process Message in 16-Word Blocks
首先定义4个辅助函数,每个函数的输入是三个32位的字,输出是一个32位的字:

        F(X,Y,Z) = XY v not(X) Z
        G(X,Y,Z) = XZ v Y not(Z)
        H(X,Y,Z) = X xor Y xor Z
        I(X,Y,Z) = Y xor (X v not(Z))

NOTE:not(X)代表X的按位补运算,X v Y 表示X和Y的按位或运算,X xor Y代表X和Y的按位异或运算,XY代表X和Y的按位与运算。

具体过程如下:
 1 /* Process each 16-word block. */
 2    For i = 0 to N/16-1 do
 3 
 4      /* Copy block i into X. */
 5      For j = 0 to 15 do
 6        Set X[j] to M[i*16+j].
 7      end /* of loop on j */

 8 
 9      /* Save A as AA, B as BB, C as CC, and D as DD. */
10      AA = A
11      BB =
 B
12      CC =
 C
13      DD =
 D
14 

15      /* Round 1. */
16      /* Let [abcd k s i] denote the operation
17           a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */

18      /* Do the following 16 operations. */
19      [ABCD  0  7  1]  [DABC  1 12  2]  [CDAB  2 17  3]  [BCDA  3 22  4]
20      [ABCD  4  7  5]  [DABC  5 12  6]  [CDAB  6 17  7]  [BCDA  7 22  8
]
21      [ABCD  8  7  9]  [DABC  9 12 10]  [CDAB 10 17 11]  [BCDA 11 22 12
]
22      [ABCD 12  7 13]  [DABC 13 12 14]  [CDAB 14 17 15]  [BCDA 15 22 16
]
23 

24      /* Round 2. */
25      /* Let [abcd k s i] denote the operation
26           a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */

27      /* Do the following 16 operations. */
28      [ABCD  1  5 17]  [DABC  6  9 18]  [CDAB 11 14 19]  [BCDA  0 20 20]
29      [ABCD  5  5 21]  [DABC 10  9 22]  [CDAB 15 14 23]  [BCDA  4 20 24
]
30      [ABCD  9  5 25]  [DABC 14  9 26]  [CDAB  3 14 27]  [BCDA  8 20 28
]
31      [ABCD 13  5 29]  [DABC  2  9 30]  [CDAB  7 14 31]  [BCDA 12 20 32
]
32 

33      /* Round 3. */
34      /* Let [abcd k s t] denote the operation
35           a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */

36      /* Do the following 16 operations. */
37      [ABCD  5  4 33]  [DABC  8 11 34]  [CDAB 11 16 35]  [BCDA 14 23 36]
38      [ABCD  1  4 37]  [DABC  4 11 38]  [CDAB  7 16 39]  [BCDA 10 23 40
]
39      [ABCD 13  4 41]  [DABC  0 11 42]  [CDAB  3 16 43]  [BCDA  6 23 44
]
40      [ABCD  9  4 45]  [DABC 12 11 46]  [CDAB 15 16 47]  [BCDA  2 23 48
]
41 

42      /* Round 4. */
43      /* Let [abcd k s t] denote the operation
44           a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */

45      /* Do the following 16 operations. */
46      [ABCD  0  6 49]  [DABC  7 10 50]  [CDAB 14 15 51]  [BCDA  5 21 52]
47      [ABCD 12  6 53]  [DABC  3 10 54]  [CDAB 10 15 55]  [BCDA  1 21 56
]
48      [ABCD  8  6 57]  [DABC 15 10 58]  [CDAB  6 15 59]  [BCDA 13 21 60
]
49      [ABCD  4  6 61]  [DABC 11 10 62]  [CDAB  2 15 63]  [BCDA  9 21 64
]
50 

51      /* Then perform the following additions. (That is increment each
52 
        of the four registers by the value it had before this block
53         was started.) */

54      A = A + AA
55      B = B +
 BB
56      C = C +
 CC
57      D = D +
 DD
58 

59    end /* of loop on i */

2.5 Output
报文摘要的产生后的形式为:A,B,C,D。也就是低位字节A开始,高位字节D结束。

3. C++ Implementation
有了上面5个步骤的算法描述,用C++实现起来就很直接了。需要注意的是在具体实现的时候上述5个步骤的顺序会有所变动,因为在大多数情况下我们都无法或很难提前计算出输入信息的长度b(如输入信息来自文件或网络)。因此在具体实现时Append Padding BitsAppend Length这两步会放在最后面。

4. Test Suite
由于实现代码比较长,在这里就不贴出来了,在本文后面会提供下载。MD5类的public接口如下:
md5.h
 1 class MD5 {
 2 public
:
 3 
    MD5();
 4     MD5(const void*
input, size_t length);
 5     MD5(const string&
str);
 6     MD5(ifstream &
in);
 7     void update(const void*
input, size_t length);
 8     void update(const string&
str);
 9     void update(ifstream&
in);
10     const byte*
 digest();
11 
    string toString();
12     void
 reset();
13 
    ...
14 };

下面简单介绍一下具体用法:
1.计算字符串的MD5值
下面的代码计算字符串"abc"的MD5值并用cout输出:
1 MD5 md5;
2 md5.update("abc"
);
3 cout << md5.toString() <<
 endl;
4 //或者更简单点

5 cout << MD5("abc").toString() << endl;

2.计算文件的MD5值
下面的代码计算文本文件"D:\test.txt"的MD5值并用cout输出,如果是二进制文件打开的时候记得要指定ios::binary模式。另外需要注意的是用来计算的文件必须存在,所以最好在计算前先判断下ifstream的状态。
(本来判断ifstream是否有效不该是客户的责任,原本想在ifstream无效时用文件名做参数抛出FileNotFoundException之类的异常,后来却发现从ifstream中居然无法得到文件名...)
1 MD5 md5;
2 md5.update(ifstream("D:\\test.txt"
));
3 cout << md5.toString() <<
 endl;
4 //或者更简单点

5 cout << MD5(ifstream("D:\\test.txt")).toString() << endl;

3.最基本的用法
上面的用来计算字符串和文件MD5值的接口都是为了方便才提供的,其实最基本的接口是:
void update(const void *input, size_t length);
update的另外两个重载都是基于它来实现的,下面的代码用上述接口来实现FileDigest函数,该函数用来计算文件的MD5值:
 1 string FileDigest(const string& file) {
 2 

 3     ifstream in(file.c_str(), ios::binary);
 4     if (!
in)
 5         return ""
;
 6 

 7     MD5 md5;
 8 
    std::streamsize length;
 9     char buffer[1024
];
10     while (!
in.eof()) {
11         in.read(buffer, 1024
);
12         length =
 in.gcount();
13         if (length > 0
)
14 
            md5.update(buffer, length);
15 
    }
16 
    in.close();
17     return
 md5.toString();
18 }

下面看看测试代码:
test.cpp
 1 #include "md5.h"
 2 #include <iostream>
 3 
 4 using namespace std;
 5 

 6 void PrintMD5(const string& str, MD5& md5) {
 7     cout << "MD5(\"" << str << "\") = " << md5.toString() <<
 endl;
 8 
}
 9 

10 int main() {
11 

12     MD5 md5;
13     md5.update(""
);
14     PrintMD5(""
, md5);
15 

16     md5.update("a");
17     PrintMD5("a"
, md5);
18 

19     md5.update("bc");
20     PrintMD5("abc"
, md5);
21 

22     md5.update("defghijklmnopqrstuvwxyz");
23     PrintMD5("abcdefghijklmnopqrstuvwxyz"
, md5);
24 

25     md5.reset();
26     md5.update("message digest"
);
27     PrintMD5("message digest"
, md5);
28 

29     md5.reset();
30     md5.update(ifstream("D:\\test.txt"
));
31     PrintMD5("D:\\test.txt"
, md5);
32 

33     return 0;
34 }

测试结果:
MD5("") = d41d8cd98f00b204e9800998ecf8427e
MD5("a") = 0cc175b9c0f1b6a831c399e269772661
MD5("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
MD5("message digest") = f96b697d7cb7938d525a2f31aaf161d0
MD5("D:\test.txt") = 7ac66c0f148de9519b8bd264312c4d64


源代码下载:点击下载
在这里放上Vrcats修改的Qt版本:点击下载

posted on 2007-09-11 12:20 蚂蚁终结者 阅读(57335) 评论(121)  编辑 收藏 引用 所属分类: Encrypt

评论共2页: 1 2 

Feedback

# re: MD5算法的C++实现[未登录] 2007-09-24 15:45 flyman

现在还用不着,收藏了,免得以后费劲。  回复  更多评论   

# re: MD5算法的C++实现 2007-10-18 10:14 MonkeyLin

有个bug, 很小,但是不注意会导致很严重的问题:
bytesToHexString return的是局部变量str, 应该把return str 改为return string(str);
// md5.cpp: line 321-332
string MD5::bytesToHexString(const byte *input, size_t length) {
string str;
str.reserve(length << 1);
for(size_t 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;
}
  回复  更多评论   

# re: MD5算法的C++实现 2007-10-18 10:27 蚂蚁终结者

@MonkeyLin
thanks!不过我想你没有仔细看代码,string是按值返回的,不存在任何问题。
如果返回值类型是string&或string*,才会出现你说的返回局部变量的问题。
另外,return str;与return string(str);并无本质区别。
  回复  更多评论   

# re: MD5算法的C++实现 2007-10-22 11:21 MonkeyLin

@蚂蚁终结者
呵呵,这两天又好好研究了下,发现是我之前不够仔细,对c++的return理解不正确,所以搞错了,刚学c++不久,让大家见笑了 :-)  回复  更多评论   

# re: MD5算法的C++实现 2007-10-22 13:24 蚂蚁终结者

@MonkeyLin
都是学习嘛,互相讨论会更有收获呵呵。  回复  更多评论   

# re: MD5算法的C++实现 2007-11-09 10:59 MonkeyLin

如果要移植到64位机器上(我的是GCC4.1),要记得把
typedef unsigned long ulong;
改为
typedef unsigned int ulong;
要不然算出来的都是错的

64位下面的GCC4.1中int是32位,long是64位
32位Win32下面VC7中int是32位,long是32位
给后面的人提个醒,省得多走弯路。。。

BTW: ICU里面的头文件不错, 针对不同的机器和平台统一定义了uint32_t, int64_t这些类型,名字直观,大大方便了移植,特别是对开发机是win32,服务器是64位其它平台的,有兴趣可以去看
http://www.icu-project.org/  回复  更多评论   

# re: MD5算法的C++实现 2007-11-10 10:49 蚂蚁终结者

@MonkeyLin
thanks!
ICU记得以前编译Boost库时下载过。
在64位机器上确实会有问题,不过为了简单,也为了减少对库的依赖性,把
typedef unsigned long ulong;
改成
typedef unsigned int uint32;
基本就够用了。
已经更新了源代码^_^  回复  更多评论   

# re: MD5算法的C++实现 2008-03-13 16:05 gg

用了一下这个源代码,可是计算文件的md5值和专门软件算出来的不一样。。。
这个。。。。  回复  更多评论   

# re: MD5算法的C++实现 2008-03-14 09:14 蚂蚁终结者

@gg
其实具体的用法在源代码的main函数中已经演示得很清楚了,我想你也肯定没有看文章后面的:“2.计算文件的MD5值”这一段,专门计算md5值的软件如WinMD5是以二进制形式打开文件的,所以:

string s1 = MD5(ifstream("file")).toString();
string s2 = MD5(ifstream("file", ios::binary)).toString();

s1与s2是不一样的,前一个是以文本模式打开,后一个是以二进制模式打开。
  回复  更多评论   

# re: MD5算法的C++实现 2008-04-11 10:03 redberries

写的不错,顶下,不过觉得如果把Updata()加个返回值判断是否成功可能会保险一点,还有就是下面的代码好像有点小问题,这个str的最后位置是不是应该放个'\0'啊,

// md5.cpp: line 321-332
string MD5::bytesToHexString(const byte *input, size_t length) {
string str;
str.reserve(length << 1);  //str.reserve((length << 1) + 1);
for(size_t 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]);
}
str[length>>1] = '\0'
return str;
}
  回复  更多评论   

# re: MD5算法的C++实现 2008-04-11 10:05 redberries

//str[length>>1] = '\0'
呵呵
  回复  更多评论   

# re: MD5算法的C++实现 2008-06-19 15:00 CPPLearning

在2.2 Append Length 那块第二行:

“也就是说,此时的数据长度是16个字(32bit)的整数倍。”貌似应该是32bytes,:)

  回复  更多评论   

# re: MD5算法的C++实现 2008-06-23 22:03 蚂蚁终结者

@CPPLearning
谢谢提醒,是我的疏忽呵呵!  回复  更多评论   

# re: MD5算法的C++实现 2008-07-04 14:50 路缘

刚好用上,谢谢博主  回复  更多评论   

# re: MD5算法的C++实现 2008-07-23 09:15 beejoy

@MonkeyLin
不会有问题的。  回复  更多评论   

# re: MD5算法的C++实现 2008-07-24 11:22 冰兰

真的很好,嘻嘻,谢谢谢谢  回复  更多评论   

# re: MD5算法的C++实现 2008-07-31 17:07 蔡火胜

太好了,我喜欢这个东西!  回复  更多评论   

#  你好,我编译你的代码后出现下面问题,能帮我看下吗? 2008-08-18 22:14 zhengdu

--------------------Configuration: test - Win32 Debug--------------------
Compiling...
test.cpp
c:\documents and settings\administrator\桌面\md5\md5.h(47) : error C2258: illegal pure syntax, must be '= 0'
c:\documents and settings\administrator\桌面\md5\md5.h(47) : error C2252: 'BUFFER_SIZE' : pure specifier can only be specified for functions
c:\documents and settings\administrator\桌面\md5\md5.cpp(130) : error C2065: 'BUFFER_SIZE' : undeclared identifier
c:\documents and settings\administrator\桌面\md5\md5.cpp(130) : error C2057: expected constant expression
c:\documents and settings\administrator\桌面\md5\md5.cpp(130) : error C2466: cannot allocate an array of constant size 0
c:\documents and settings\administrator\桌面\md5\md5.cpp(130) : error C2133: 'buffer' : unknown size
执行 cl.exe 时出错.

test.obj - 1 error(s), 0 warning(s)
  回复  更多评论   

# re: MD5算法的C++实现 2008-08-19 10:12 蚂蚁终结者

@zhengdu
你用的是哪个版本的VC ?VC6.0 ?

大概是你的编译器太老,不支持static const整形值的初始化语法,试试下面两种办法:

1. 将md5.h中的
static const size_t BUFFER_SIZE = 1024;
改为
enum { BUFFER_SIZE = 1024 };

2. 将md5.h中的
static const size_t BUFFER_SIZE = 1024;
改为
static const size_t BUFFER_SIZE;

并在md5.cpp的
MD5::MD5() {
reset();
}
上面加上
const size_t MD5::BUFFER_SIZE = 1024;
  回复  更多评论   

# re: MD5算法的C++实现 2008-09-01 11:37 zhongyunde

这个代码有问题吗   回复  更多评论   

# re: MD5算法的C++实现 2008-09-01 19:38 蚂蚁终结者

@zhongyunde
代码没有问题,可以放心使用!  回复  更多评论   

# re: MD5算法的C++实现 2008-10-08 14:12 wx3456

这个MD5封装类确实很好!可是怎样将MD5字符解密后还原成原来的字符啊?(不知道该调用那些函数)请举例说明!最好转换成CString类型的数据。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-08 14:28 蚂蚁终结者

@wx3456
不好意思,我不太明白你说的“MD5字符解密”是什么意思?
MD5是单向的,是没有办法从MD5值推算出原先的信息的。
从string值转换成CString很简单,google一下有很多。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-08 14:55 wx3456

我现在要做的是把用户名和密码的信息加密后保存在ini件当中 原来是用一个任意的字符串和要加密的字符进行异或运算进行加密,解密时在进行一次异或运算。可是这样做后会产生一个问题的(就是会产生不可读字符如回车,换行等等,这样在读ini文件时这些不可读的字符会读不出来)。我听说MD5加密后的字符都是普通的可以显示的字符所以我这才用MD5加密,可是如何把加密后的密码字符串恢复原样以便在用户登录时解密 和用户输入的密码对比,如果相同则登录成功,就是这个意思  回复  更多评论   

# re: MD5算法的C++实现 2008-10-08 15:06 蚂蚁终结者

@wx3456
既然MD5是单向的,那你可以换一种方式:
在用户登录时,计算用户输入的密码的MD5值,拿这个值和ini文件里的MD5比较,如果相等就允许登录(虽然多个不同的密码可能对应相同的MD5值,但是几率可以说非常小,对于一般的应用来说足够了)。

比如用户A注册时的密码为abc,计算MD5值保存在ini文件为:
900150983cd24fb0d6963f7d28e17f72

在用户A登录时,假设用户输入的密码为xxx,则计算xxx的MD5值,若和ini文件中的MD5值相等就允许登录。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-08 15:12 wx3456

恩...我觉得也是这样,以后像前辈多多请教啊,请问前辈你是研究哪方面的啊?
  回复  更多评论   

# re: MD5算法的C++实现 2008-10-08 15:30 蚂蚁终结者

@wx3456
呵呵,前辈不敢当,我大学刚毕业工作才几个月而已。目前从事C++方面的工作,有空多交流。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-08 16:11 foxtail

我用了你的这个 但是算出来的MD5和网上的一些个工具不一样啊
你有检查过吗 不知道是什么原因  回复  更多评论   

# re: MD5算法的C++实现 2008-10-08 16:17 蚂蚁终结者

@foxtail
这个是没有问题的,参考下上面我回答的:
@gg
其实具体的用法在源代码的main函数中已经演示得很清楚了,我想你也肯定没有看文章后面的:“2.计算文件的MD5值”这一段,专门计算md5值的软件如WinMD5是以二进制形式打开文件的,所以:

string s1 = MD5(ifstream("file")).toString();
string s2 = MD5(ifstream("file", ios::binary)).toString();

s1与s2是不一样的,前一个是以文本模式打开,后一个是以二进制模式打开。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-08 16:33 foxtail

恩 刚才也看到gg的了 不好意思。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-09 12:10 ktls

我试的也是不一样,不知道为什么,你说要用二进制打开文件,
string FileDigest(const string& file) {

ifstream in(file.c_str(), ios::binary);
if (!in) {
return "";
}
这不是已经是用二进制打开的吗,可得到的md5码还是和winmd5的结果不一样。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-09 14:11 蚂蚁终结者

@ktls
这个我测试过很多次了,肯定是没有问题的!
可能是你哪个地方弄错了!  回复  更多评论   

# re: MD5算法的C++实现 2008-10-09 15:19 wx3456

我现在要实现的功能是用户登录验证和用户的添加,密码修改,我把这些都保存在ini文件中的。登录验证是可以的,就是但我我修改某一用户的密码后,然后在验证这个用户的登录时缺不能通过 我调试发现用户名的加密字符对比是可以的,就是密码加密的字符对比却不相同的 代码是这样的
md5.update(PWd.GetBuffer()); t3=md5.toString().c_str(); 其中PWD是从文本框中得到的输入密码,t3是CString型的变量,这样计算出来的md5密码是(密码是1234)e19d5cd5af0378da05f63f891c7467af 而之前从ini文件中读出来的是 049ec6b8b8565dfde2007f7a9f7ecd84(这个md5密码是修改密码后重新计算写入的) 为什么两者不一样啊?导致验证失败  回复  更多评论   

# re: MD5算法的C++实现 2008-10-09 15:35 ktls

我是这样测试的,把你提供的3个文件添加到工程里去,把test.cpp里注释掉的
//md5.reset();
//md5.update(ifstream("D:\\test.txt"));
//PrintMD5("D:\\test.txt", md5);
改成我自己的文件
md5.reset();
md5.update(ifstream("C:\\abc.doc"));
PrintMD5("C:\\abc.doc", md5);
其它没有改过任何地方,执行如果如下:
MD5("") = d41d8cd98f00b204e9800998ecf8427e
MD5("a") = 0cc175b9c0f1b6a831c399e269772661
MD5("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e400
MD5("message digest") = f96b697d7cb7938d525a2f31aaf1
MD5("C:\abc.doc") = 8b30f9eef77e2ac08a19bb159bfe1495
用winmd5的检验"c:\abc.doc"文件得到的结果如下:
7dfe74280223aa9819f1617a5ef40643 abc.doc

能告诉我email地址吗,可以通过email与你讨教,也方便发送测试结果。
另外有个建议,能不能把这个做成dll,可以提供给别人直接调用。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-09 15:41 蚂蚁终结者

@wx3456
有几个地方我不太清楚,首先049ec6b8b8565dfde2007f7a9f7ecd84是什么密码加密出来的?还有1234的md5应该是81dc9bdb52d04dc20036dbd8313ed055才对。如果方便的话把源码发我帮你看看,你有msn没有?有的话加我antterminator@hotmail.com  回复  更多评论   

# re: MD5算法的C++实现 2008-10-09 15:45 蚂蚁终结者

@ktls
email:antterminator@gmail.com
msn:antterminator@hotmail.com
这样的话可能是其它的问题,那把abc.doc发给我测试下吧。
这个本来是考虑跨平台使用的,如果做成dll就只能windows用了。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-09 15:49 蚂蚁终结者

@ktls
md5.update(ifstream("C:\\abc.doc"));
刚才没注意到,ifstream默认是以文本模式打开的,改成二进制应该就可以了:
md5.update(ifstream("C:\\abc.doc", ios::binary));   回复  更多评论   

# re: MD5算法的C++实现 2008-10-09 16:07 ktls

是我自己没看清楚,我看到FileDigest里已经是用二进制打开了,就没仔细看后面调用的代码,现在已经解决,非常感谢。  回复  更多评论   

# re: MD5算法的C++实现 2008-10-09 16:10 蚂蚁终结者

@ktls
不客气,很多人用的时候都有这个问题,在这里弄清楚了免得后面的人再走弯路!  回复  更多评论   

# re: MD5算法的C++实现 2009-01-07 16:41 far

我想写一个非标准的MD5算法,有哪些参数可以任意修改?
比如ABCD的初始值,还是每次移位的位数?或者可以做更大的修改?
能够保证和标准MD5类似,冲突尽量小
  回复  更多评论   

# re: MD5算法的C++实现 2009-01-08 13:15 蚂蚁终结者

@far
其实最简单方法就是修改ABCD的初始值,哪怕只是修改其中一位数,得到的md5值也会跟标准的完全不一样。因为md5算法的整个过程都是以ABCD这4个数为基础。  回复  更多评论   

# re: MD5算法的C++实现 2009-01-09 10:14 hai

看过了,收藏!
牛人!顶下!  回复  更多评论   

# re: MD5算法的C++实现 2009-01-29 15:27 roger

很多地方都看到了这篇文章,只不过你这里多了个make文件。。。。
请问楼主这里是原创么?
谢谢  回复  更多评论   

# re: MD5算法的C++实现 2009-02-02 09:07 蚂蚁终结者

我这里是原创呵呵,不过不知道你说的make文件是什么?我这里好像没有  回复  更多评论   

# re: MD5算法的C++实现[未登录] 2009-02-13 10:04 Winter

感谢 ant 的这个类, 其实已经用了好久了, 今天才来道谢 >.<
额, 主要是想多问一个问题 - -!
如果是包含乱码的 unicode 路径在用 ifstream 的时候该怎么做呢 @@
之前 unicode 路径都是 WideCharToMultiByte 然后调用类的...
不过如果是带乱码的路径换成 ANSI 就不行了
3Q ^^  回复  更多评论   

# re: MD5算法的C++实现[未登录] 2009-02-13 10:18 Winter

:P 大概要求高了点...
如果想很好支持 UNICODE 乱码路径的话感觉整个类都需要改了
刚才试了下 WinMD5 或 Hash 这两个常用的校验软件
发现也无法支持乱码 (大概他们用的也是那个最老的标准 MD5 类吧 ^^)
anyway, thx alot : )  回复  更多评论   

# re: MD5算法的C++实现 2009-02-20 10:43 Nihlathak

问主人一个问题啊:为什么以下代码
md5.reset();
md5.update(ifstream("E:\\1.txt"));
PrintMD5("E:\\1.txt", md5);
当E盘不存在这个文件的时候也能出结果呢?
不好意思我C++小白,就想请教一下  回复  更多评论   

# re: MD5算法的C++实现 2009-02-20 12:40 蚂蚁终结者

@Nihlathak
当文件不存在的时候得到的结果肯定是错误的。
上面的例子写成那样只是为了演示用法。
最好在调用update前判断一下文件是否存在:
md5.reset();
ifstream file("E:\\1.txt");
if (!file) {
// error: can not open file
}
else {
md5.update();
PrintMD5("E:\\1.txt", md5);
}
  回复  更多评论   

# re: MD5算法的C++实现 2009-02-20 14:00 Nihlathak

呵呵,谢了  回复  更多评论   

# re: MD5算法的C++实现 2009-02-23 11:33 凉风

你好我想问下 像加密后我要还原 那该怎么还原   回复  更多评论   

# re: MD5算法的C++实现 2009-02-23 11:38 蚂蚁终结者

@凉风
md5算法是一种hash算法,是单向的,还原是不可能的。因为多份数据可能计算出相同的md5值。  回复  更多评论   

# re: MD5算法的C++实现 2009-02-23 19:54 roger

引用你的code,需要收费么?收的话收多少?  回复  更多评论   

# re: MD5算法的C++实现 2009-02-23 20:01 蚂蚁终结者

@roger
呵呵,哥们说笑了,不收费,若是觉得不错的话直接用就行了!  回复  更多评论   

# re: MD5算法的C++实现 2009-02-26 19:40 roger

多谢楼主。这要是在美国,说不定楼主就发财了。
可以雇些律师,去告使用你code的人;)
  回复  更多评论   

# re: MD5算法的C++实现 2009-03-07 07:19 chang

我现在想在16bits系统中实现MD5,能给些建议吗?还有,不调用update函数可以吗?谢谢!  回复  更多评论   

# re: MD5算法的C++实现 2009-03-07 11:56 蚂蚁终结者

@chang
16位系统下应该可以拿上面的代码移植,比如需要把md5.h中的
typedef unsigned int uint32;
改为
typedef unsigned long uint32;
可能还需要改动其他代码,我这里没有条件测试,你不妨测试一下。

update是唯一的接口,不调用是不行的呵呵。  回复  更多评论   

# re: MD5算法的C++实现 2009-04-05 17:12 anyangtao

string str1 = "abcdefghijklmn";
md5.update(str1);
cout << md5.toString() << endl;
cout << MD5("abcdefghijklmn").toString() << endl;
string str2 = str1 ;
md5.update(str2);
cout << md5.toString() << endl;

前两个输出的值相同,但第三个输出和前两个输出的并不一样,未找出原因,望指点。  回复  更多评论   

# re: MD5算法的C++实现 2009-04-05 17:29 蚂蚁终结者

调用update是有累加效果的,上面的代码:
...
md5.update(str1);
...
md5.update(str2);
实际上得到的是"abcdefghijklmnabcdefghijklmn"的md5值

如果想重复使用某个MD5对象,需要在下次update前先reset,如下:
...
string str2 = str1 ;
//这里加上reset
md5.reset();
md5.update(str2);
...
  回复  更多评论   

# 链接变量的初始化问题 2009-04-08 01:22 csu_boy

为什么用 _state[0] = 0x67452301;
_state[1] = 0xefcdab89;
_state[2] = 0x98badcfe;
_state[3] = 0x10325476;
这些值
而不是网上说的
_state[0] = 0x01234567;
_state[1] = 0x89abcdef;
_state[2] = 0xfedcba98;
_state[3] = 0x76543210;
我用下面的值算就对应不了标准的MD5值了  回复  更多评论   

# re: MD5算法的C++实现 2009-04-08 11:52 蚂蚁终结者

@csu_boy
这个是Endian的问题,本文中md5的实现是基于Little Endian的机器,所以要写成下面这样:
_state[0] = 0x67452301;
_state[1] = 0xefcdab89;
_state[2] = 0x98badcfe;
_state[3] = 0x10325476;
如果是Big Endian的机器,则要写成:
_state[0] = 0x01234567;
_state[1] = 0x89abcdef;
_state[2] = 0xfedcba98;
_state[3] = 0x76543210;
  回复  更多评论   

# re: MD5算法的C++实现 2009-04-16 15:45 csu_boy

据说MD5连文件的属性改变了也会计算出不同的MD5值,是这么回事吗?  回复  更多评论   

# re: MD5算法的C++实现 2009-04-16 16:31 蚂蚁终结者

@csu_boy
这个应该是跟计算md5值的软件实现有关,一般来说都只看文件内容,内容相同的文件md5就是一样的  回复  更多评论   

# re: MD5算法的C++实现 2009-04-27 22:35 MM

该程序怎样修改可以实现对数字(例:ip包净核)的认证呢?请指教!  回复  更多评论   

# re: MD5算法的C++实现 2009-04-27 23:03 蚂蚁终结者

@MM
你是要计算纯数据的md5值?
那可以用这个重载方法:
void update(const void* input, size_t length);

比如:
1.计算一个int的md5值:
int i = 12345;
MD5 md;
md.update(&i, sizeof(i));
cout << md.toString() << endl;

2.计算一个struct的md5值:
struct Package {
char buffer[32];
int i;
//...
};

Package pkg;
MD5 md;
md.update(&pkg, sizeof(pkg));
cout << md.toString() << endl;

不知道这是否是你想要的功能?  回复  更多评论   

# re: MD5算法的C++实现 2009-04-30 11:16 adang

蚂蚁终结者,请问一下有没有“test.txt”文件?可以的话,麻烦传给我一份(还有加密后的结果)。我现在用的是QT版本的那个MD5算法,想验证一下加密出来的结果是否和你们的一致,字符串的已经可以了,现在只剩下文件加密了。我的邮箱:adang322@126.com。谢谢!  回复  更多评论   

# re: MD5算法的C++实现 2009-05-27 08:50 windcao

我移植了一个到symbian上
下载:http://download.csdn.net/source/1355073
我的MSN: windcao@hotmail.com  回复  更多评论   

# re: MD5算法的C++实现 2009-05-27 11:25 windcao

http://download.csdn.net/source/1355214
以这个为准,刚才那个有点别的问题编译出错。

  回复  更多评论   

# re: MD5算法的C++实现 2009-06-09 15:36 lalalal

非常感谢那位提醒64位的同学。。。  回复  更多评论   

# re: MD5算法的C++实现 2009-08-29 16:56 nofree

嗯,写得不错,不过那个大端小端的问题可以很容易实现嘛,干嘛用32位常量直接赋值呢?一个字节一个字节来赋值就ok了,我说的是下面这里:
_state[0] = 0x67452301;
_state[1] = 0xefcdab89;
_state[2] = 0x98badcfe;
_state[3] = 0x10325476;
  回复  更多评论   

# re: MD5算法的C++实现 2009-09-07 23:55 summer

谢谢!  回复  更多评论   

# re: MD5算法的C++实现 2009-09-17 16:45 jaosnjee

我发现有BUG  回复  更多评论   

# 我发现有BUG 2009-09-17 16:51 jaosnjee

根据WIKI百科的MD5介绍,他们给出了三个例子:
一般128位的MD5散列被表示为32位十六进制数字。以下是一个43位长ASCII字母列的MD5散列:
MD5("The quick brown fox jumps over the lazy dog")
= 9e107d9d372bb6826bd81d3542a419d6
即使在原文中作一个小变化(比如用c取代d)其散列也会发生巨大的变化:
MD5("The quick brown fox jumps over the lazy cog")
= 1055d3e698d289f2af8663725127bd4b
空文的散列为:
MD5("")
= d41d8cd98f00b204e9800998ecf8427e
为什么我在用你的程序验证The quick brown fox jumps over the lazy dog得到了相同的结果,而把这句话中c取代d后却得不到相同的结果?我之后又将c改回d,连续算两变,居然得到不同的MD5值!!!  回复  更多评论   

# 不好意思搞错了,关于"我发现有BUG" 2009-09-17 17:01 jaosnjee

没有在两次计算间插入
md5.reset();
不好意思,有点搅局了.
楼主啊,你的参考代码怎么也不在每次计算后都加上
md5.reset();啊?害我瞎忙活
  回复  更多评论   

# re: 不能下载 2010-01-07 16:20 光光兔

不能下载啊.兄弟.
只有Vrcats修改的Qt版本可以下载.

看得我眼谗哦.呵呵.
请帮我发到wcg_0321@163.com好吗?  回复  更多评论   

# re: 不能下载 2010-01-07 16:21 光光兔

不能下载啊.兄弟.
只有Vrcats修改的Qt版本可以下载.

看得我眼谗哦.呵呵.
请帮我发到wcg_0321@163.com好吗?  回复  更多评论   

# re: MD5算法的C++实现 2010-07-05 15:35 cll

借用了,非常感谢。  回复  更多评论   

# re: MD5算法的C++实现[未登录] 2010-08-30 23:34 liu

你好,看了你的介绍之后懂了不少,不过我比较笨还是有很多不懂,我的理解是这样的:假如第一次update(str1),然后打印str1的md5,接着update(str2),这时str1的前strlen(str1)-strlen(str1)%64个字符应该不用再处理(transform)了吧,那么程序在哪里保存前面strlen(str1)-strlen(str1)%64个字符的transform结果的呢?  回复  更多评论   

# re: MD5算法的C++实现[未登录] 2010-08-31 21:53 liu

唉,昨天没仔细看,明明就有一个oldState.现在大体流程是看懂了,呵呵  回复  更多评论   

# re: MD5算法的C++实现 2010-09-19 00:08 Wind

蚂蚁大哥,弱弱的请教下:T[i]是什么意思?你在md5.cpp中直接传进去的一串16进制字符又代表什么意思?  回复  更多评论   

# re: MD5算法的C++实现 2010-11-05 23:58 Tidus

@Wind
常数T[i]可以如下选择:
在第i步中,T[i]是4294967296*abs(sin(i))的整数部分,i的单位是弧度。
可参考http://www.ietf.org/rfc/rfc1321.txt  回复  更多评论   

# re: MD5算法的C++实现 2011-03-24 11:35 yun

为什么把程序移植到MFC中就出现 错误
Unhandled exception at 0x0002ded0 in .exe: 0xC0000005: Access violation.  回复  更多评论   

# re: MD5算法的C++实现 2011-06-15 21:05 Tim

学习~  回复  更多评论   

# re: MD5算法的C++实现 2011-07-22 16:46 士大夫

用这个计算文件好像不对  回复  更多评论   

# re: MD5算法的C++实现 2011-07-25 11:40 马灯

@士大夫
对的,注意打开方式,上面有帖子说明  回复  更多评论   

# re: MD5算法的C++实现[未登录] 2011-08-03 21:58 JAMES

你好,如果要产生16位的MD5,该怎么办
求助
ifdyo@hotmail.com  回复  更多评论   

# re: MD5算法的C++实现 2011-08-25 10:34 IT

你好,我想问一下 将输入信息的原始长度b(bit)表示成一个64-bit的数字 这句话怎么理解,比如我输入的是 "abcdefghijk", 怎么表示成一个64bit的数字 。。  回复  更多评论   

# re: MD5算法的C++实现 2011-12-08 05:37 RiggsCaitlin34

I think that to get the <a href="http://goodfinance-blog.com/topics/business-loans">business loans</a> from creditors you ought to present a firm motivation. However, one time I have got a short term loan, just because I wanted to buy a bike.   回复  更多评论   

# re: MD5算法的C++实现 2012-01-12 15:57 aaa

我发现对中文进行加密时结果不对,是不是有问题?  回复  更多评论   

# re: MD5算法的C++实现 2012-03-15 10:21 常超

着急用,先拿来啊。回头再好好看看。  回复  更多评论   

# re: MD5算法的C++实现 2012-03-22 18:18 wyk

谢谢分享,下来看过,接口设计很好,学习  回复  更多评论   

# re: MD5算法的C++实现 2012-04-11 17:50 sean

谢谢分享,质量不错的代码。  回复  更多评论   

# re: MD5算法的C++实现 2012-04-30 02:22 Comparatif forfait mobile

你好,看了你的介绍之后懂了不少,不过我比较笨还是有很多不懂,我的理解是这样的:假如第一次update(str1),然后打印str1的md5,接着update(str2),这时str1的前strlen(str1)-strlen(str1)%64个字符应该不用再处理(transform)了吧,那么程序在哪里保存前面strlen(str1)-strlen(str1)%64个字符的transform结果的呢? 回复 更多评论   回复  更多评论   

# re: MD5算法的C++实现 2012-05-02 11:17 狂奔的蜗牛

@光光兔
您好!能给我发一份Vrcats修改的Qt版本吗?麻烦您了,谢谢!!!急需~~~我的QQ:690905539
  回复  更多评论   

# re: MD5算法的C++实现 2012-05-02 11:20 狂奔的蜗牛

@VrcatS
您好:能给我发一份吗? 我的QQ:690905539 谢谢~~~急需  回复  更多评论   

# re: MD5算法的C++实现 2012-08-20 21:53 aking

学习了!很多地方看不太懂,收藏起来了。实在看不懂就直接用啦!  回复  更多评论   

# re: MD5算法的C++实现 2012-09-04 15:19 xwj

同样一个文件,中文路径和英文路径计算出来的md5码不一样。

中文路径下,所有的文件计算出来的md5码都一样,

英文路径下没问题。

请指点,32581991@qq.com  回复  更多评论   

# re: MD5算法的C++实现 2012-10-23 21:13 WWE

为什么
md5.update("bc");
PrintMD5("abc", md5);
不需要reset
而后面
md5.reset();
md5.update("message digest");
PrintMD5("message digest", md5);
需要呢?  回复  更多评论   

# re: MD5算法的C++实现 2013-11-07 20:55 Dan

想请问一下,那个我该怎么在主函数中调用MD5算法  回复  更多评论   

# re: MD5算法的C++实现 2014-05-13 19:51 snoopy

你好,我想请问一下,对于字节串如何按512位分块,需要先转化为对应的二进制编码吗  回复  更多评论   

# re: MD5算法的C++实现 2014-11-29 01:47 KomeijiKuroko

建议在md5.h的声明部分,
MD5(ifstream& in);
加上explicit,

#Md5.h line 20
explicit MD5(ifstream& in);

要不然 MD5(ifstream("File")) 时候,IntelliSense总是把 ifstream("File")看成到MD5的隐式转换,和

#md5.h line 37
private:
MD5(const MD5&);

矛盾  回复  更多评论   

评论共2页: 1 2 

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理