安全访问认证
C++实现
#include<iostream>
#include<string>
using
namespace
std;
#define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))//右移的时候,高位一定要补零,而不是补充符号位
#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 A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476
//strBaye的长度
unsigned
int
strlength;
//A,B,C,D的临时变量
unsigned
int
atemp;
unsigned
int
btemp;
unsigned
int
ctemp;
unsigned
int
dtemp;
//常量ti unsigned int(abs(sin(i+1))*(2pow32))
const
unsigned
int
k[]={
0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,
0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,
0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,
0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,
0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,
0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,
0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,
0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391};
//向左位移数
const
unsigned
int
s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,
12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
15,21,6,10,15,21,6,10,15,21,6,10,15,21};
const
char
str16[]=
"0123456789abcdef"
;
void
mainLoop(unsigned
int
M[])
{
unsigned
int
f,g;
unsigned
int
a=atemp;
unsigned
int
b=btemp;
unsigned
int
c=ctemp;
unsigned
int
d=dtemp;
for
(unsigned
int
i = 0; i < 64; i++)
{
if
(i<16){
f=F(b,c,d);
g=i;
}
else
if
(i<32)
{
f=G(b,c,d);
g=(5*i+1)%16;
}
else
if
(i<48){
f=H(b,c,d);
g=(3*i+5)%16;
}
else
{
f=I(b,c,d);
g=(7*i)%16;
}
unsigned
int
tmp=d;
d=c;
c=b;
b=b+shift((a+f+k[i]+M[g]),s[i]);
a=tmp;
}
atemp=a+atemp;
btemp=b+btemp;
ctemp=c+ctemp;
dtemp=d+dtemp;
}
/*
*填充函数
*处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
*填充方式为先加一个1,其它位补零
*最后加上64位的原来长度
*/
unsigned
int
* add(string str)
{
unsigned
int
num=((str.length()+8)/64)+1;
//以512位,64个字节为一组
unsigned
int
*strByte=
new
unsigned
int
[num*16];
//64/4=16,所以有16个整数
strlength=num*16;
for
(unsigned
int
i = 0; i < num*16; i++)
strByte[i]=0;
for
(unsigned
int
i=0; i <str.length(); i++)
{
strByte[i>>2]|=(str[i])<<((i%4)*8);
//一个整数存储四个字节,i>>2表示i/4 一个unsigned int对应4个字节,保存4个字符信息
}
strByte[str.length()>>2]|=0x80<<(((str.length()%4))*8);
//尾部添加1 一个unsigned int保存4个字符信息,所以用128左移
/*
*添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位
*/
strByte[num*16-2]=str.length()*8;
return
strByte;
}
string changeHex(
int
a)
{
int
b;
string str1;
string str=
""
;
for
(
int
i=0;i<4;i++)
{
str1=
""
;
b=((a>>i*8)%(1<<8))&0xff;
//逆序处理每个字节
for
(
int
j = 0; j < 2; j++)
{
str1.insert(0,1,str16[b%16]);
b=b/16;
}
str+=str1;
}
return
str;
}
string getMD5(string source)
{
atemp=A;
//初始化
btemp=B;
ctemp=C;
dtemp=D;
unsigned
int
*strByte=add(source);
for
(unsigned
int
i=0;i<strlength/16;i++)
{
unsigned
int
num[16];
for
(unsigned
int
j=0;j<16;j++)
num[j]=strByte[i*16+j];
mainLoop(num);
}
return
changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp));
}
unsigned
int
main()
{
string ss;
// cin>>ss;
string s=getMD5(
"abc"
);
cout<<s;
return
0;
}
JAVA实现
public
class
MD5{
/*
*四个链接变量
*/
private
final
int
A=
0x67452301
;
private
final
int
B=
0xefcdab89
;
private
final
int
C=
0x98badcfe
;
private
final
int
D=
0x10325476
;
/*
*ABCD的临时变量
*/
private
int
Atemp,Btemp,Ctemp,Dtemp;
/*
*常量ti
*公式:floor(abs(sin(i+1))×(2pow32)
*/
private
final
int
K[]={
0xd76aa478
,
0xe8c7b756
,
0x242070db
,
0xc1bdceee
,
0xf57c0faf
,
0x4787c62a
,
0xa8304613
,
0xfd469501
,
0x698098d8
,
0x8b44f7af
,
0xffff5bb1
,
0x895cd7be
,
0x6b901122
,
0xfd987193
,
0xa679438e
,
0x49b40821
,
0xf61e2562
,
0xc040b340
,
0x265e5a51
,
0xe9b6c7aa
,
0xd62f105d
,
0x02441453
,
0xd8a1e681
,
0xe7d3fbc8
,
0x21e1cde6
,
0xc33707d6
,
0xf4d50d87
,
0x455a14ed
,
0xa9e3e905
,
0xfcefa3f8
,
0x676f02d9
,
0x8d2a4c8a
,
0xfffa3942
,
0x8771f681
,
0x6d9d6122
,
0xfde5380c
,
0xa4beea44
,
0x4bdecfa9
,
0xf6bb4b60
,
0xbebfbc70
,
0x289b7ec6
,
0xeaa127fa
,
0xd4ef3085
,
0x04881d05
,
0xd9d4d039
,
0xe6db99e5
,
0x1fa27cf8
,
0xc4ac5665
,
0xf4292244
,
0x432aff97
,
0xab9423a7
,
0xfc93a039
,
0x655b59c3
,
0x8f0ccc92
,
0xffeff47d
,
0x85845dd1
,
0x6fa87e4f
,
0xfe2ce6e0
,
0xa3014314
,
0x4e0811a1
,
0xf7537e82
,
0xbd3af235
,
0x2ad7d2bb
,
0xeb86d391
};
/*
*向左位移数,计算方法未知
*/
private
final
int
s[]={
7
,
12
,
17
,
22
,
7
,
12
,
17
,
22
,
7
,
12
,
17
,
22
,
7
,
12
,
17
,
22
,
5
,
9
,
14
,
20
,
5
,
9
,
14
,
20
,
5
,
9
,
14
,
20
,
5
,
9
,
14
,
20
,
4
,
11
,
16
,
23
,
4
,
11
,
16
,
23
,
4
,
11
,
16
,
23
,
4
,
11
,
16
,
23
,
6
,
10
,
15
,
21
,
6
,
10
,
15
,
21
,
6
,
10
,
15
,
21
,
6
,
10
,
15
,
21
};
/*
*初始化函数
*/
private
void
init(){
Atemp=A;
Btemp=B;
Ctemp=C;
Dtemp=D;
}
/*
*移动一定位数
*/
private
int
shift(
int
a,
int
s){
return
(a<<s)|(a>>>(
32
-s));
//右移的时候,高位一定要补零,而不是补充符号位
}
/*
*主循环
*/
private
void
MainLoop(
int
M[]){
int
F,g;
int
a=Atemp;
int
b=Btemp;
int
c=Ctemp;
int
d=Dtemp;
for
(
int
i =
0
; i <
64
; i ++){
if
(i<
16
){
F=(b&c)|((~b)&d);
g=i;
}
else
if
(i<
32
){
F=(d&b)|((~d)&c);
g=(
5
*i+
1
)%
16
;
}
else
if
(i<
48
){
F=b^c^d;
g=(
3
*i+
5
)%
16
;
}
else
{
F=c^(b|(~d));
g=(
7
*i)%
16
;
}
int
tmp=d;
d=c;
c=b;
b=b+shift(a+F+K[i]+M[g],s[i]);
a=tmp;
}
Atemp=a+Atemp;
Btemp=b+Btemp;
Ctemp=c+Ctemp;
Dtemp=d+Dtemp;
}
/*
*填充函数
*处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
*填充方式为先加一个0,其它位补零
*最后加上64位的原来长度
*/
private
int
[] add(String str){
int
num=((str.length()+
8
)/
64
)+
1
;
//以512位,64个字节为一组
int
strByte[]=
new
int
[num*
16
];
//64/4=16,所以有16个整数
for
(
int
i=
0
;i<num*
16
;i++){
//全部初始化0
strByte[i]=
0
;
}
int
i;
for
(i=
0
;i<str.length();i++){
strByte[i>>
2
]|=str.charAt(i)<<((i%
4
)*
8
);
//一个整数存储四个字节,小端序
}
strByte[i>>
2
]|=
0x80
<<((i%
4
)*
8
);
//尾部添加1
/*
*添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位
*/
strByte[num*
16
-
2
]=str.length()*
8
;
return
strByte;
}
/*
*调用函数
*/
public
String getMD5(String source){
init();
int
strByte[]=add(source);
for
(
int
i=
0
;i<strByte.length/
16
;i++){
int
num[]=
new
int
[
16
];
for
(
int
j=
0
;j<
16
;j++){
num[j]=strByte[i*
16
+j];
}
MainLoop(num);
}
return
changeHex(Atemp)+changeHex(Btemp)+changeHex(Ctemp)+changeHex(Dtemp);
}
/*
*整数变成16进制字符串
*/
private
String changeHex(
int
a){
String str=
""
;
for
(
int
i=
0
;i<
4
;i++){
str+=String.format(
"%2s"
, Integer.toHexString(((a>>i*
8
)%(
1
<<
8
))&
0xff
)).replace(
' '
,
'0'
);
}
return
str;
}
/*
*单例
*/
private
static
MD5 instance;
public
static
MD5 getInstance(){
if
(instance==
null
){
instance=
new
MD5();
}
return
instance;
}
private
MD5(){};
public
static
void
main(String[] args){
String str=MD5.getInstance().getMD5(
""
);
System.out.println(str);
}
}
VB2010实现
Imports
System
Imports
System.Security.Cryptography
Imports
System.Text
Module
Example
'哈希输入字符串并返回一个 32 字符的十六进制字符串哈希。
Function
GetMd5Hash(
ByVal
input
As
String
)
As
String
'创建新的一个 MD5CryptoServiceProvider 对象的实例。
Dim
md5Hasher
As
New
MD5CryptoServiceProvider()
'输入的字符串转换为字节数组,并计算哈希。
Dim
data
As
Byte
() = md5Hasher.ComputeHash(Encoding.
Default
.GetBytes(input))
'创建一个新的 StringBuilder 收集的字节,并创建一个字符串。
Dim
sBuilder
As
New
StringBuilder()
'通过每个字节的哈希数据和格式为十六进制字符串的每一个循环。
For
i
As
Integer
= 0
To
data.Length - 1
sBuilder.Append(data(i).ToString(
"x2"
))
Next
'返回十六进制字符串。
Return
sBuilder.ToString()
End
Function
'验证对一个字符串的哈希值。
Function
VerifyMd5Hash(
ByVal
input
As
String
,
ByVal
hash
As
String
)
As
Boolean
'哈希的输入。
Dim
hashOfInput
As
String
= GetMd5Hash(input)
'创建 StringComparer 的哈希进行比较。
Dim
comparer
As
StringComparer = StringComparer.OrdinalIgnoreCase
Return
comparer.Compare(hashOfInput, hash) = 0
End
Function
Sub
Main()
Dim
source
As
String
=
"Hello World!"
Dim
hash
As
String
= GetMd5Hash(source)
Console.WriteLine($
"进行MD5加密的字符串为:{source},加密的结果是:{hash}。"
)
Console.WriteLine(
"正在验证哈希……"
)
If
VerifyMd5Hash(source, hash)
Then
Console.WriteLine("哈希值是
相同的。")
Else
Console.WriteLine(
"哈希值是不相同的。"
)
EndIf
EndSub
EndModule
'此代码示例产生下面的输出:
'进行MD5加密的字符串为:Hello World!,加密的结果是:ed076287532e86365e841e92bfc50d8c。
'正在验证哈希……
'哈希值是相同的。
JavaScript实现
unction
md5(string) {
function
md5_RotateLeft(lValue, iShiftBits) {
return
(lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}
function
md5_AddUnsigned(lX, lY) {
var
lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if
(lX4 & lY4) {
return
(lResult ^ 0x80000000 ^ lX8 ^ lY8);
}
if
(lX4 | lY4) {
if
(lResult & 0x40000000) {
return
(lResult ^ 0xC0000000 ^ lX8 ^ lY8);
}
else
{
return
(lResult ^ 0x40000000 ^ lX8 ^ lY8);
}
}
else
{
return
(lResult ^ lX8 ^ lY8);
}
}
function
md5_F(x, y, z) {
return
(x & y) | ((~x) & z);
}
function
md5_G(x, y, z) {
return
(x & z) | (y & (~z));
}
function
md5_H(x, y, z) {
return
(x ^ y ^ z);
}
function
md5_I(x, y, z) {
return
(y ^ (x | (~z)));
}
function
md5_FF(a, b, c, d, x, s, ac) {
a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_F(b, c, d), x), ac));
return
md5_AddUnsigned(md5_RotateLeft(a, s), b);
};
function
md5_GG(a, b, c, d, x, s, ac) {
a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_G(b, c, d), x), ac));
return
md5_AddUnsigned(md5_RotateLeft(a, s), b);
};
function
md5_HH(a, b, c, d, x, s, ac) {
a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_H(b, c, d), x), ac));
return
md5_AddUnsigned(md5_RotateLeft(a, s), b);
};
function
md5_II(a, b, c, d, x, s, ac) {
a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_I(b, c, d), x), ac));
return
md5_AddUnsigned(md5_RotateLeft(a, s), b);
};
function
md5_ConvertToWordArray(string) {
var
lWordCount;
var
lMessageLength = string.length;
var
lNumberOfWords_temp1 = lMessageLength + 8;
var
lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
var
lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
var
lWordArray = Array(lNumberOfWords - 1);
var
lBytePosition = 0;
var
lByteCount = 0;
while
(lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return
lWordArray;
};
function
md5_WordToHex(lValue) {
var
WordToHexValue =
""
,
WordToHexValue_temp =
""
,
lByte, lCount;
for
(lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
WordToHexValue_temp =
"0"
+ lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
}
return
WordToHexValue;
};
function
md5_Utf8Encode(string) {
string = string.replace(/\r\n/g,
"\n"
);
var
utftext =
""
;
for
(
var
n = 0; n < string.length; n++) {
var
c = string.charCodeAt(n);
if
(c < 128) {
utftext += String.fromCharCode(c);
}
else
if
((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else
{
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return
utftext;
};
var
x = Array();
var
k, AA, BB, CC, DD, a, b, c, d;
var
S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22;
var
S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20;
var
S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23;
var
S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21;
string = md5_Utf8Encode(string);
x = md5_ConvertToWordArray(string);
a = 0x67452301;
b = 0xEFCDAB89;
c = 0x98BADCFE;
d = 0x10325476;
for
(k = 0; k < x.length; k += 16) {
AA = a;
BB = b;
CC = c;
DD = d;
a = md5_FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
d = md5_FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
c = md5_FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
b = md5_FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
a = md5_FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
d = md5_FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
c = md5_FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
b = md5_FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
a = md5_FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
d = md5_FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
c = md5_FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
b = md5_FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
a = md5_FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
d = md5_FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
c = md5_FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
b = md5_FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
a = md5_GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
d = md5_GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
c = md5_GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
b = md5_GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
a = md5_GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
d = md5_GG(d, a, b, c, x[k + 10], S22, 0x2441453);
c = md5_GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
b = md5_GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
a = md5_GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
d = md5_GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
c = md5_GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
b = md5_GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
a = md5_GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
d = md5_GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
c = md5_GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
b = md5_GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
a = md5_HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
d = md5_HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
c = md5_HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
b = md5_HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
a = md5_HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
d = md5_HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
c = md5_HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
b = md5_HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
a = md5_HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
d = md5_HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
c = md5_HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
b = md5_HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
a = md5_HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
d = md5_HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
c = md5_HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
b = md5_HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
a = md5_II(a, b, c, d, x[k + 0], S41, 0xF4292244);
d = md5_II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
c = md5_II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
b = md5_II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
a = md5_II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
d = md5_II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
c = md5_II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
b = md5_II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
a = md5_II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
d = md5_II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
c = md5_II(c, d, a, b, x[k + 6], S43, 0xA3014314);
b = md5_II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
a = md5_II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
d = md5_II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
c = md5_II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
b = md5_II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
a = md5_AddUnsigned(a, AA);
b = md5_AddUnsigned(b, BB);
c = md5_AddUnsigned(c, CC);
d = md5_AddUnsigned(d, DD);
}
return
(md5_WordToHex(a) + md5_WordToHex(b) + md5_WordToHex(c) + md5_WordToHex(d)).toLowerCase();
}
伪代码实现
//Note:Allvariablesareunsigned32bitsandwrapmodulo2^32whencalculatingvarint[64]r,k//rspecifiestheper-roundshiftamountsr[0..15]:={7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22}r[16..31]:={5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20}r[32..47]:={4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23}r[48..63]:={6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21}//Usebinaryintegerpartofthesinesofintegersasconstants:forifrom0to63k[i]:=floor(abs(sin(i+1))×2^32)//Initializevariables:varinth0:=0x67452301varinth1:=0xEFCDAB89varinth2:=0x98BADCFEvarinth3:=0x10325476//Pre-processing:append"1"bittomessageappend"0"bitsuntilmessagelengthinbits≡448(mod512)appendbitlengthofmessageas64-bitlittle-endianintegertomessage//Processthemessageinsuccessive512-bitchunks:foreach512-bitchunkofmessagebreakchunkintosixteen32-bitlittle-endianwordsw[i],0≤i≤15//Initializehashvalueforthischunk:varinta:=h0varintb:=h1varintc:=h2varintd:=h3//Mainloop:forifrom0to63if0≤i≤15thenf:=(bandc)or((notb)andd)g:=ielseif16≤i≤31f:=(dandb)or((notd)andc)g:=(5×i+1)mod16elseif32≤i≤47f:=bxorcxordg:=(3×i+5)mod16elseif48≤i≤63f:=cxor(bor(notd))g:=(7×i)mod16temp:=dd:=cc:=bb:=((a+f+k[i]+w[g])leftrotater[i])+ba:=temp//Addthischunk'shashtoresultsofar:h0:=h0+ah1:=h1+bh2:=h2+ch3:=h3+dvarintdigest:=h0appendh1appendh2appendh3//(expressedaslittle-endian)MD5加密工具
王小云
破解MD5密码算法,运算量达到2的80次方。即使采用现在最快的巨型计算机,也要运算100万年以上才能破解。但王小云和她的研究小组用普通的个人电脑,几分钟内就可以找到有效结果。
【摘自 百度百科 只是略有感触 想收藏下】