Base64和MD5加密

Base64--网络传输

自从引用以来,Base64编码的标准极普及为的迅速。不过,把文件作为附件通过网际邮件扩充协议(MIME)传送时,Base64是标准的编码标准。然而,几乎所有的电子邮件客户端都是用MIME发送文件(以附件形式)的,这就意味着大多数的电子邮件客户端使用Base64对文件编码后通过网络传输。格式如下:

Content-Transfer-Encodingbase64Gb2312

这种传输格式又被称为U-t-UUnixto Unix)传输协议,能兼容大多数的硬件设备并基于其上进行无损字节传输。但是缺点在于是,使用此种格式会使文件的大小增加百分之四十左右。

除了作为MIME的默认编码标准,base64编码也广泛用于其他领域。一个常见的例子是用于网络服务器完成基于HTTP的基本认证。当服务器想限制访问某些文件时,通过使用基于HTTP的基本认证系统,便可以对这些文件进行密码保护。而基本认证使用Base64编码标准对用户名和密码进行编码。这样,黑客们使用TCP通过端口连接ESMTP服务器时,手动输入量就会大大增加。

尽管Base64编码受到广泛的支持和应用,但却是当今最弱的编码标准之一,通过以下步骤就可以轻易地进行逆向工程。不仅仅是算法上的容易逆向,因为在网络上Base64用纯文本形式发送密码,使得Base64加密文本很容易受到sniffer程序的嗅探。

编码程序如下:

  1. 将要加密的文本的每个字符转换成标准的ASCII十进制码。

  2. 通过任何一种方式(手算、机器算、对照表格)将这部分十进制编码转换成二进制(文章最后附有转换表)编码。每个十进制码都对应器等价的八位二进制数值。

  3. 将这部分二进制数连结到一起,产生一串二进制数。

  4. 将这一大片的二进制字符串分割成每6个字符为一部分的小块。

  5. 通过任何一种方式(手算、机器算、对照表格)将这部分6字符的小块分别转换成相应的等价十进制数。

  6. 通过Base64表转换成Base64编码。

Base64编码转换表如下:

十进制

编码

十进制

编码

十进制

编码

十进制

编码

0

A

16

Q

32

g

48

w

1

B

17

R

33

h

49

x

2

C

18

S

34

i

50

y

3

D

19

T

35

j

51

z

4

E

20

U

36

k

52

0

5

F

21

V

37

l

53

1

6

G

22

W

38

m

54

2

7

H

23

X

39

n

55

3

8

I

24

Y

40

o

56

4

9

J

25

Z

41

p

57

5

10

K

26

a

42

q

58

6

11

L

27

b

43

r

59

7

12

M

28

c

44

s

60

8

13

N

29

d

45

t

61

9

14

O

30

e

46

u

62

+

15

P

31

f

47

v

63

/

例如:mne,通过ASCII字符表转化为是进制值为:m109n110e101.合起来就是:109110101.转化为二进制就是:01101101 0110 1110 0110 0101。将它们分成六个字为一段:011011010110 111001 100101。而他们对应的十进制字符分别是:2722 57 37Base64等价值就是:27b22w575371,也就是说mneBase64编码是bw51

需要注意的是:如果被加密的字符串每3个一组,还剩12个字符,使用特殊字符“=补齐Base64成为4个字。

知道了加密方式,要逆向就很简单了。将对应的Base64值转换为十进制,再通过计算转换成二进制编码。将这一串码分为81组,得到十进制码,最后再等价到相应的ASCII编码即可。

1ASCII编码表(部分)

二进制

十进制

十六进制

缩写/字符

解释

00000000

0

00

NUL(null)

空字符

00000001

1

01

SOH(start of handing)

标题开始

00000010

2

02

STX(start of text)

正文开始 

00000011

3

03

ETX(end of text)

正文结束

00000100

4

04

EOT(end of transmission)

传输结束

00000101

5

05

ENQ(enquiry)

请求

00000110

6

06

ACK(acknowledge)

收到通知

00000111

7

07

BEL(bell)

响铃

00001000

8

08

BS(backspace)

退格

00001001

9

09

HT(horizontal tab)

水平制表符

00001010

10

0A

LF(NL line feed, new line)

换行键

00001011

11

0B

VT(vertical tab)

垂直制表符

00001100

12

0C

FF(NP form feed, new page)

换页键

00001101

13

0D

CR(carriage return)

回车键

00001110

14

0E

SO(shift out)

不用切换

00001111

15

0F

SI(shift in)

启用切换

00010000

16

10

DLE(data link escape)

数据链路转义

00010001

17

11

DC1(device control 1)

设备控制1

00010010

18

12

DC2(device control 2)

设备控制2

00010011

19

13

DC3(device control 3)

设备控制3

00010100

20

14

DC4(device control 4)

设备控制4

00010101

21

15

NAK(negative acknowledge)

拒绝接收

00010110

22

16

SYN(synchronous idle)

同步空闲

00010111

23

17

ETB(end of trans. block)

传输块结束

00011000

24

18

CAN(cancel)

取消

00011001

25

19

EM(end of medium)

介质中断

00011010

26

1A

SUB(substitute)

替补

00011011

27

1B

ESC(escape)

溢出

00011100

28

1C

FS(file separator)

文件分割符

00011101

29

1D

GS(group separator)

分组符

00011110

30

1E

RS(record separator)

记录分离符

00011111

31

1F

US(unit separator)

单元分隔符

2:下列Perl脚本将会自动帮你做解密:

UseMIME::Base64

Printdecode_base64(“Insert Text here”);


3:使用Java脚本实现解密(代码):

<scripttype="text/javascript">

varbase64EncodeChars ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

varbase64DecodeChars = new Array(

-1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

-1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

-1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,

52,53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,

-1,0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,

15,16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,

-1,26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,

41,42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);


functionbase64Encode(str) {

varout, i, len;

varc1, c2, c3;


len= str.length;

i= 0;

out= "";

while(i< len) {

c1= str.charCodeAt(i++) & 0xff;

if(i== len)

{

out+= base64EncodeChars.charAt(c1 >> 2);

out+= base64EncodeChars.charAt((c1 & 0x3) << 4);

out+= "==";

break;

}

c2= str.charCodeAt(i++);

if(i== len)

{

out+= base64EncodeChars.charAt(c1 >> 2);

out+= base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 &0xF0) >> 4));

out+= base64EncodeChars.charAt((c2 & 0xF) << 2);

out+= "=";

break;

}

c3= str.charCodeAt(i++);

out+= base64EncodeChars.charAt(c1 >> 2);

out+= base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 &0xF0) >> 4));

out+= base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 &0xC0) >>6));

out+= base64EncodeChars.charAt(c3 & 0x3F);

}

returnout;

}


functionbase64Decode(str) {

varc1, c2, c3, c4;

vari, len, out;


len= str.length;

i= 0;

out= "";

while(i< len) {

/*c1 */

do{

c1= base64DecodeChars[str.charCodeAt(i++) & 0xff];

}while(i < len && c1 == -1);

if(c1== -1)

break;


/*c2 */

do{

c2= base64DecodeChars[str.charCodeAt(i++) & 0xff];

}while(i < len && c2 == -1);

if(c2== -1)

break;


out+= String.fromCharCode((c1 << 2) | ((c2 & 0x30) >>4));


/*c3 */

do{

c3= str.charCodeAt(i++) & 0xff;

if(c3== 61)

returnout;

c3= base64DecodeChars[c3];

}while(i < len && c3 == -1);

if(c3== -1)

break;


out+= String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C)>> 2));


/*c4 */

do{

c4= str.charCodeAt(i++) & 0xff;

if(c4== 61)

returnout;

c4= base64DecodeChars[c4];

}while(i < len && c4 == -1);

if(c4== -1)

break;

out+= String.fromCharCode(((c3 & 0x03) << 6) | c4);

}

returnout;

}

alert("原文:"+sTemp+"\n加密:"+base64Encode(sTemp)+"\n解密:"+base64Decode(base64Encode(sTemp)));

alert("原文:"+sTemp+"\n加密:"+base64Encode(sTemp)+"\n解密:"+base64Decode(base64Encode(sTemp)));

</script>



MD5

1.简介

MD5的全称是Message-Digest Algorithm 5(信息-摘要算法),在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明,经MD2、MD3和MD4发展而来。 http://www.ietf.org/rfc/rfc1321.txt,是一份最权威的文档,由ronaldl. rivest19928月向ieft提交。

Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了“字节串”而不是“字符串”这个词,是因为这种变换只与字节的值有关,与字符集或编码方式无关。

MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法 将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。

MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫 readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内 容,你对这个文件重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。

MD5还广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以MD5值(或类似的其它算法)的方式保存的,用户Login的时候,系统是把用户输入的密码计算成MD5值,然后再去和系统中保存的MD5值进行比较,而系统并不“知道”用户的密码是什么。

一些黑客破获这种密码的方法是一种被称为“跑字典”的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用MD5程序计算出这些字典项的MD5值,然后再用目标的MD5值在这个字典中检索。

即使假设密码的最大长度为8,同时密码只能是字母和数字,共26+26+10=62个字符,排列组合出的字典的项数则是 P(62,1)+P(62,2)….+P(62,8),那也已经是一个很天文的数字了,存储这个字典就需要TB级的磁盘组,而且这种方法还有一个前提,就 是能获得目标账户的密码MD5值的情况下才可以。

2.用途

MD5的作用是对一段信息(message)生成信息摘要(message-digest),该摘要对该信息具有唯一性,可以作为数字签名。用于验证文件的有效性(是否有丢失或损坏的数据),对用户密码的加密,在哈希函数中计算散列值。

MD5的典型应用
(1).密码加密
将用户设置的密码进行md5运算后存入数据库。当用户登录时,只需再求一次md5值,并与数据库中的值进行比对。判断密码是否正确就知道用户的合法性了。 因为md5不可逆,所以即使数据库被突破或下载,也不可能知道用户密码。而这样带来的问题就是用户也不能找回密码,而只能在达成一定的条件后让用户重置密码。这就是为什么现在越来越多的网站不能找回密码,而只能重置密码。因为多数使用了不可逆算法(此处不只md5,也包括其它不可逆算法的应用)。
对于有找回密码功能的系统,密码机制要更加注意,要么你存储的就是明文,要么密码加密的机制是可以反向破解的。

(2).文件校验
因为md5的重码率低到只存在理论可能,因此常被用来校验数据是否被篡改(或者检查文件是否下载正确)。我们常见的,一些下载网站会给出文件的md5值,以供用户在下载后校验(一般称为 "check sum" or md5sum) ,因为即使在下载过程中,只改动了一个字节,其md5值也会改变。


3.特点

MD5采用的是对输入的任意长度的消息进行运算,产生一个128位的消息摘要,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串。



4.说明

唯一性和不可逆性都不是绝对的,从理论上分析是一种多对一的关系,但两个不同的信息产生相同摘要的概率很小。不可逆是指从输出反推输入所需的运算量和计算时间太大,使用穷搜字典的方法又需要太多的存储空间。

5.算法描述


算法输入是一个字节串,每个字节是8bit.

算法的执行分为以下几个步骤:


第一步,补位:

MD5算法先对输入的数据进行补位,使得数据的长度(byte为单位)64求余的结果是56

即数据扩展至LEN=K*64+56个字节,K为整数。

补位方法:补一个1,然后补0至满足上述要求。相当于补一个0x80的字节,再补值

0的字节。这一步里总共补充的字节数为063个。


第二步,附加数据长度:

用一个64位的整数表示数据的原始长度(bit为单位),将这个数字的8个字节按低位的在前,

高位在后的顺序附加在补位后的数据后面。这时,数据被填补后的总长度为:

LEN= K*64+56+8=(K+1)*64 Bytes


※注意那个64位整数是输入数据的原始长度而不是填充字节后的长度,我就在这里栽了跟头.


第三步,初始化MD5参数:

有四个32位整数变量(A,B,C,D)用来计算信息摘要,每一个变量被初始化成以下

以十六进制数表示的数值,低位的字节在前面。

wordA: 01 23 45 67

wordB: 89 ab cd ef

wordC: fe dc ba 98

wordD: 76 54 32 10

※注意低位的字节在前面指的是LittleEndian平台上内存中字节的排列方式,

而在程序中书写时,要写成:

A=0x67452301

B=0xefcdab89

C=0x98badcfe

D=0x10325476


第四步,定义四个MD5基本的按位操作函数:

XYZ32位整数。

F(X,Y,Z)= (X and Y) or (not(X) and Z)

G(X,Y,Z)= (X and Z) or (Y and not(Z))

H(X,Y,Z)= X xor Y xor Z

I(X,Y,Z)= Y xor (X or not(Z))


再定义四个分别用于四轮变换的函数。

Mj表示消息的第j个子分组(从015),<<<s表示循环左移s位,则四种操作为:

FF(a,b,c,d,Mj,s,ti)表示a=b+((a+(F(b,c,d)+Mj+ti)<<<s)

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

HH(a,b,c,d,Mj,s,ti)表示a=b+((a+(H(b,c,d)+Mj+ti)<<<s)

II(a,b,c,d,Mj,s,ti)表示a=b+((a+(I(b,c,d)+Mj+ti)<<<s)



第五步,对输入数据作变换。

处理数据,N是总的字节数,以64个字节为一组,每组作一次循环,每次循环进行四轮操作。

要变换的64个字节用1632位的整数数组M[0...15]表示。而数组T[1... 64]表示一组常数,

T[i]4294967296*abs(sin(i))32位整数部分,i的单位是弧度,i的取值从164

具体过程如下:


/*设置主循环变量*/

Fori = 0 to N/16-1 do


/*每循环一次,把数据原文存放在16个元素的数组X.*/

Forj = 0 to 15 do

SetX[j] to M[i*16+j].

end/结束对J的循环


/*Save A as AA, B as BB, C as CC, and D as DD.

*/

AA= A

BB= B

CC= C

DD= D


/*1*/

/* [abcdk s i]表示如下操作

a= b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */

/*Do the following 16 operations. */

[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4]

[ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8]

[ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12]

[ABCD12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]



/*2**/

/* [abcdk s i]表示如下操作

a= b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */

/*Do the following 16 operations. */

[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20]

[ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]

[ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28]

[ABCD13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]


/*3*/

/* [abcdk s i]表示如下操作

a= b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */

/*Do the following 16 operations. */

[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]

[ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40]

[ABCD13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]

[ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]



/*4*/

/* [abcdk s i]表示如下操作

a= b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */

/*Do the following 16 operations. */

[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]

[ABCD12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]

[ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]

[ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]


/*然后进行如下操作*/

A= A + AA

B= B + BB

C= C + CC

D= D + DD


Nexti /* 结束对I的循环*/


第六步,输出结果。

ABCD连续存放,共16个字节,128位。按十六进制依次输出这个16个字节。



最后,用程序语言实现算法后,可以输入以下几个信息对程序作一个简单的测试,

看看程序有没有错误。

 MD5("") = d41d8cd98f00b204e9800998ecf8427e

 MD5("a") = 0cc175b9c0f1b6a831c399e269772661

 MD5("abc") = 900150983cd24fb0d6963f7d28e17f72

 MD5("message digest") = f96b697d7cb7938d525a2f31aaf161d0

 MD5("abcdefghijklmnopqrstuvwxyz") =c3fcd3d76192e4007dfb496cca67e13b

 MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")=

d174ab98d277d9f5a5611c2c9f419d9f

MD5("123456789012345678901234567890123456789012345678901234567890123456789

01234567890")= 57edf4a22be3c955ac49da2e2107b67a



MD5算法之C#程序


[code]

//源文件:md5.cs

//MD5 Alogrithm

//by rufi 2004.6.20 http://rufi.yculblog.com/

usingSystem;

usingSystem.Collections;

usingSystem.IO;


publicclass MD5 {

//staticstate variables

privatestatic UInt32 A;

privatestatic UInt32 B;

privatestatic UInt32 C;

privatestatic UInt32 D;


//numberof bits to rotate in tranforming

privateconst int S11 = 7;

privateconst int S12 = 12;

privateconst int S13 = 17;

privateconst int S14 = 22;

privateconst int S21 = 5;

privateconst int S22 = 9;

privateconst int S23 = 14;

privateconst int S24 = 20;

privateconst int S31 = 4;

privateconst int S32 = 11;

privateconst int S33 = 16;

privateconst int S34 = 23;

privateconst int S41 = 6;

privateconst int S42 = 10;

privateconst int S43 = 15;

privateconst int S44 = 21;



/*F, G, H and I are basic MD5 functions.

*四个非线性函数:

*

*F(X,Y,Z) =(X&Y)|((~X)&Z)

*G(X,Y,Z) =(X&Z)|(Y&(~Z))

*H(X,Y,Z) =X^Y^Z

*I(X,Y,Z)=Y^(X|(~Z))

*

*&与,|或,~非,^异或)

*/

privatestatic UInt32 F(UInt32 x,UInt32 y,UInt32 z){

return(x&y)|((~x)&z);

}

privatestatic UInt32 G(UInt32 x,UInt32 y,UInt32 z){

return(x&z)|(y&(~z));

}

privatestatic UInt32 H(UInt32 x,UInt32 y,UInt32 z){

returnx^y^z;

}

privatestatic UInt32 I(UInt32 x,UInt32 y,UInt32 z){

returny^(x|(~z));

}


/*FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.

*Rotation is separate from addition to prevent recomputation.

*/

privatestatic void FF(ref UInt32 a,UInt32 b,UInt32 c,UInt32 d,UInt32 mj,ints,UInt32 ti){

a= a + F(b,c,d) + mj + ti;

a= a << s | a >> (32-s);

a+= b;

}

privatestatic void GG(ref UInt32 a,UInt32 b,UInt32 c,UInt32 d,UInt32 mj,ints,UInt32 ti){

a= a + G(b,c,d) + mj + ti;

a= a << s | a >> (32-s);

a+= b;

}

privatestatic void HH(ref UInt32 a,UInt32 b,UInt32 c,UInt32 d,UInt32 mj,ints,UInt32 ti){

a= a + H(b,c,d) + mj + ti;

a= a << s | a >> (32-s);

a+= b;

}

privatestatic void II(ref UInt32 a,UInt32 b,UInt32 c,UInt32 d,UInt32 mj,ints,UInt32 ti){

a= a + I(b,c,d) + mj + ti;

a= a << s | a >> (32-s);

a+= b;

}


privatestatic void MD5_Init(){

A=0x67452301; //in memory, this is 0x01234567

B=0xefcdab89; //in memory, this is 0x89abcdef

C=0x98badcfe; //in memory, this is 0xfedcba98

D=0x10325476; //in memory, this is 0x76543210

}


privatestatic UInt32[] MD5_Append(byte[] input){

intzeros=0;

intones =1;

intsize=0;

intn = input.Length;

intm = n%64;

if(m < 56 ){

zeros= 55-m;

size=n-m+64;

}

elseif (m==56){

zeros= 0;

ones= 0;

size=n+8;

}

else{

zeros= 63-m+56;

size=n+64-m+64;

}


ArrayListbs = new ArrayList(input);

if(ones==1){

bs.Add((byte)0x80 ); // 0x80 = $10000000

}

for(inti=0;i<zeros;i++){

bs.Add((byte)0 );

}


UInt64N = (UInt64) n * 8;

byteh1=(byte)(N&0xFF);

byteh2=(byte)((N>>8)&0xFF);

byteh3=(byte)((N>>16)&0xFF);

byteh4=(byte)((N>>24)&0xFF);

byteh5=(byte)((N>>32)&0xFF);

byteh6=(byte)((N>>40)&0xFF);

byteh7=(byte)((N>>48)&0xFF);

byteh8=(byte)(N>>56);

bs.Add(h1);

bs.Add(h2);

bs.Add(h3);

bs.Add(h4);

bs.Add(h5);

bs.Add(h6);

bs.Add(h7);

bs.Add(h8);

byte[]ts=(byte[])bs.ToArray(typeof(byte));


/*Decodes input (byte[]) into output (UInt32[]). Assumes len is

*a multiple of 4.

*/

UInt32[]output = new UInt32[size/4];

for(Int64i=0,j=0;i<size;j++,i+=4){

output[j]=(UInt32)(ts[i]| ts[i+1]<<8 | ts[i+2]<<16 | ts[i+3]<<24);

}

returnoutput;

}

privatestatic UInt32[] MD5_Trasform(UInt32[] x){


UInt32a,b,c,d;


for(intk=0;k<x.Length;k+=16){

a=A;

b=B;

c=C;

d=D;

/*Round 1 */

FF(ref a, b, c, d, x[k+ 0], S11, 0xd76aa478); /* 1 */

FF(ref d, a, b, c, x[k+ 1], S12, 0xe8c7b756); /* 2 */

FF(ref c, d, a, b, x[k+ 2], S13, 0x242070db); /* 3 */

FF(ref b, c, d, a, x[k+ 3], S14, 0xc1bdceee); /* 4 */

FF(ref a, b, c, d, x[k+ 4], S11, 0xf57c0faf); /* 5 */

FF(ref d, a, b, c, x[k+ 5], S12, 0x4787c62a); /* 6 */

FF(ref c, d, a, b, x[k+ 6], S13, 0xa8304613); /* 7 */

FF(ref b, c, d, a, x[k+ 7], S14, 0xfd469501); /* 8 */

FF(ref a, b, c, d, x[k+ 8], S11, 0x698098d8); /* 9 */

FF(ref d, a, b, c, x[k+ 9], S12, 0x8b44f7af); /* 10 */

FF(ref c, d, a, b, x[k+10], S13, 0xffff5bb1); /* 11 */

FF(ref b, c, d, a, x[k+11], S14, 0x895cd7be); /* 12 */

FF(ref a, b, c, d, x[k+12], S11, 0x6b901122); /* 13 */

FF(ref d, a, b, c, x[k+13], S12, 0xfd987193); /* 14 */

FF(ref c, d, a, b, x[k+14], S13, 0xa679438e); /* 15 */

FF(ref b, c, d, a, x[k+15], S14, 0x49b40821); /* 16 */


/*Round 2 */

GG(ref a, b, c, d, x[k+ 1], S21, 0xf61e2562); /* 17 */

GG(ref d, a, b, c, x[k+ 6], S22, 0xc040b340); /* 18 */

GG(ref c, d, a, b, x[k+11], S23, 0x265e5a51); /* 19 */

GG(ref b, c, d, a, x[k+ 0], S24, 0xe9b6c7aa); /* 20 */

GG(ref a, b, c, d, x[k+ 5], S21, 0xd62f105d); /* 21 */

GG(ref d, a, b, c, x[k+10], S22, 0x2441453); /* 22 */

GG(ref c, d, a, b, x[k+15], S23, 0xd8a1e681); /* 23 */

GG(ref b, c, d, a, x[k+ 4], S24, 0xe7d3fbc8); /* 24 */

GG(ref a, b, c, d, x[k+ 9], S21, 0x21e1cde6); /* 25 */

GG(ref d, a, b, c, x[k+14], S22, 0xc33707d6); /* 26 */

GG(ref c, d, a, b, x[k+ 3], S23, 0xf4d50d87); /* 27 */

GG(ref b, c, d, a, x[k+ 8], S24, 0x455a14ed); /* 28 */

GG(ref a, b, c, d, x[k+13], S21, 0xa9e3e905); /* 29 */

GG(ref d, a, b, c, x[k+ 2], S22, 0xfcefa3f8); /* 30 */

GG(ref c, d, a, b, x[k+ 7], S23, 0x676f02d9); /* 31 */

GG(ref b, c, d, a, x[k+12], S24, 0x8d2a4c8a); /* 32 */


/*Round 3 */

HH(ref a, b, c, d, x[k+ 5], S31, 0xfffa3942); /* 33 */

HH(ref d, a, b, c, x[k+ 8], S32, 0x8771f681); /* 34 */

HH(ref c, d, a, b, x[k+11], S33, 0x6d9d6122); /* 35 */

HH(ref b, c, d, a, x[k+14], S34, 0xfde5380c); /* 36 */

HH(ref a, b, c, d, x[k+ 1], S31, 0xa4beea44); /* 37 */

HH(ref d, a, b, c, x[k+ 4], S32, 0x4bdecfa9); /* 38 */

HH(ref c, d, a, b, x[k+ 7], S33, 0xf6bb4b60); /* 39 */

HH(ref b, c, d, a, x[k+10], S34, 0xbebfbc70); /* 40 */

HH(ref a, b, c, d, x[k+13], S31, 0x289b7ec6); /* 41 */

HH(ref d, a, b, c, x[k+ 0], S32, 0xeaa127fa); /* 42 */

HH(ref c, d, a, b, x[k+ 3], S33, 0xd4ef3085); /* 43 */

HH(ref b, c, d, a, x[k+ 6], S34, 0x4881d05); /* 44 */

HH(ref a, b, c, d, x[k+ 9], S31, 0xd9d4d039); /* 45 */

HH(ref d, a, b, c, x[k+12], S32, 0xe6db99e5); /* 46 */

HH(ref c, d, a, b, x[k+15], S33, 0x1fa27cf8); /* 47 */

HH(ref b, c, d, a, x[k+ 2], S34, 0xc4ac5665); /* 48 */


/*Round 4 */

II(ref a, b, c, d, x[k+ 0], S41, 0xf4292244); /* 49 */

II(ref d, a, b, c, x[k+ 7], S42, 0x432aff97); /* 50 */

II(ref c, d, a, b, x[k+14], S43, 0xab9423a7); /* 51 */

II(ref b, c, d, a, x[k+ 5], S44, 0xfc93a039); /* 52 */

II(ref a, b, c, d, x[k+12], S41, 0x655b59c3); /* 53 */

II(ref d, a, b, c, x[k+ 3], S42, 0x8f0ccc92); /* 54 */

II(ref c, d, a, b, x[k+10], S43, 0xffeff47d); /* 55 */

II(ref b, c, d, a, x[k+ 1], S44, 0x85845dd1); /* 56 */

II(ref a, b, c, d, x[k+ 8], S41, 0x6fa87e4f); /* 57 */

II(ref d, a, b, c, x[k+15], S42, 0xfe2ce6e0); /* 58 */

II(ref c, d, a, b, x[k+ 6], S43, 0xa3014314); /* 59 */

II(ref b, c, d, a, x[k+13], S44, 0x4e0811a1); /* 60 */

II(ref a, b, c, d, x[k+ 4], S41, 0xf7537e82); /* 61 */

II(ref d, a, b, c, x[k+11], S42, 0xbd3af235); /* 62 */

II(ref c, d, a, b, x[k+ 2], S43, 0x2ad7d2bb); /* 63 */

II(ref b, c, d, a, x[k+ 9], S44, 0xeb86d391); /* 64 */


A+=a;

B+=b;

C+=c;

D+=d;

}

returnnew UInt32[]{A,B,C,D};

}

publicstatic byte[] MD5Array(byte[] input){

MD5_Init();

UInt32[]block = MD5_Append(input);

UInt32[]bits = MD5_Trasform(block);


/*Encodes bits (UInt32[]) into output (byte[]). Assumes len is

*a multiple of 4.

*/

byte[]output=new byte[bits.Length*4];

for(inti=0,j=0;i<bits.Length;i++,j+=4){

output[j]= (byte)(bits[i] & 0xff);

output[j+1]= (byte)((bits[i] >> 8) & 0xff);

output[j+2]= (byte)((bits[i] >> 16) & 0xff);

output[j+3]= (byte)((bits[i] >> 24) & 0xff);

}

returnoutput;

}


publicstatic string ArrayToHexString(byte[] array,bool uppercase){

stringhexString="";

stringformat="x2";

if(uppercase){

format="X2";

}

foreach(byteb in array){

hexString+= b.ToString(format);

}

returnhexString;

}


publicstatic string MDString(string message){

char[]c = message.ToCharArray();

byte[]b = new byte[c.Length];

for(inti=0;i<c.Length;i++){

b[i]=(byte)c[i];

}

byte[]digest = MD5Array(b);

returnArrayToHexString(digest,false);

}

publicstatic string MDFile(string fileName){

FileStreamfs=File.Open(fileName,FileMode.Open,FileAccess.Read);

byte[]array=new byte[fs.Length];

fs.Read(array,0,(int)fs.Length);

byte[]digest = MD5Array(array);

fs.Close();

returnArrayToHexString(digest,false);

}


publicstatic string Test(string message){

return"rnMD5 (""+message+"") = " +MD5.MDString(message);

}

publicstatic string TestSuite(){

strings = "";

s+=Test("");

s+=Test("a");

s+=Test("abc");

s+=Test("messagedigest");

s+=Test("abcdefghijklmnopqrstuvwxyz");

s+=Test("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");

s+=Test("12345678901234567890123456789012345678901234567890123456789012345678901234567890");

returns;

}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值