MD5加密原理Word文档格式.docx
《MD5加密原理Word文档格式.docx》由会员分享,可在线阅读,更多相关《MD5加密原理Word文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
用一个64位的整数表示数据的原始长度(以bit为单位),将这个数字的8个字节按低位的在前,
高位在后的顺序附加在补位后的数据后面。
这时,数据被填补后的总长度为:
LEN=K*64+56+8=(K+1)*64Bytes。
※注意那个64位整数是输入数据的原始长度而不是填充字节后的长度,我就在这里栽了跟头.
第三步,初始化MD5参数:
有四个32位整数变量(A,B,C,D)用来计算信息摘要,每一个变量被初始化成以下
以十六进制数表示的数值,低位的字节在前面。
wordA:
01234567
wordB:
89abcdef
wordC:
fedcba98
wordD:
76543210
※注意低位的字节在前面指的是LittleEndian平台上内存中字节的排列方式,
而在程序中书写时,要写成:
A=0x67452301
B=0xefcdab89
C=0x98badcfe
D=0x10325476
第四步,定义四个MD5基本的按位操作函数:
X,Y,Z为32位整数。
F(X,Y,Z)=(XandY)or(not(X)andZ)
G(X,Y,Z)=(XandZ)or(Yandnot(Z))
H(X,Y,Z)=XxorYxorZ
I(X,Y,Z)=Yxor(Xornot(Z))
再定义四个分别用于四轮变换的函数。
设Mj表示消息的第j个子分组(从0到15),<
<
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)<
HH(a,b,c,d,Mj,s,ti)表示a=b+((a+(H(b,c,d)+Mj+ti)<
II(a,b,c,d,Mj,s,ti)表示a=b+((a+(I(b,c,d)+Mj+ti)<
第五步,对输入数据作变换。
处理数据,N是总的字节数,以64个字节为一组,每组作一次循环,每次循环进行四轮操作。
要变换的64个字节用16个32位的整数数组M[0...15]表示。
而数组T[1...64]表示一组常数,
T[i]为4294967296*abs(sin(i))的32位整数部分,i的单位是弧度,i的取值从1到64。
具体过程如下:
/*设置主循环变量*/
Fori=0toN/16-1do
/*每循环一次,把数据原文存放在16个元素的数组X中.*/
Forj=0to15do
SetX[j]toM[i*16+j].
end/结束对J的循环
/*SaveAasAA,BasBB,CasCC,andDasDD.
*/
AA=A
BB=B
CC=C
DD=D
/*第1轮*/
/*以[abcdksi]表示如下操作
a=b+((a+F(b,c,d)+X[k]+T[i])<
s).*/
/*Dothefollowing16operations.*/
[ABCD071][DABC1122][CDAB2173][BCDA3224]
[ABCD475][DABC5126][CDAB6177][BCDA7228]
[ABCD879][DABC91210][CDAB101711][BCDA112212]
[ABCD12713][DABC131214][CDAB141715][BCDA152216]
/*第2轮**/
a=b+((a+G(b,c,d)+X[k]+T[i])<
[ABCD1517][DABC6918][CDAB111419][BCDA02020]
[ABCD5521][DABC10922][CDAB151423][BCDA42024]
[ABCD9525][DABC14926][CDAB31427][BCDA82028]
[ABCD13529][DABC2930][CDAB71431][BCDA122032]
/*第3轮*/
a=b+((a+H(b,c,d)+X[k]+T[i])<
[ABCD5433][DABC81134][CDAB111635][BCDA142336]
[ABCD1437][DABC41138][CDAB71639][BCDA102340]
[ABCD13441][DABC01142][CDAB31643][BCDA62344]
[ABCD9445][DABC121146][CDAB151647][BCDA22348]
/*第4轮*/
a=b+((a+I(b,c,d)+X[k]+T[i])<
[ABCD0649][DABC71050][CDAB141551][BCDA52152]
[ABCD12653][DABC31054][CDAB101555][BCDA12156]
[ABCD8657][DABC151058][CDAB61559][BCDA132160]
[ABCD4661][DABC111062][CDAB21563][BCDA92164]
/*然后进行如下操作*/
A=A+AA
B=B+BB
C=C+CC
D=D+DD
Nexti/*结束对I的循环*/
第六步,输出结果。
A,B,C,D连续存放,共16个字节,128位。
按十六进制依次输出这个16个字节。
最后,用程序语言实现算法后,可以输入以下几个信息对程序作一个简单的测试,
看看程序有没有错误。
MD5("
"
)=d41d8cd98f00b204e9800998ecf8427e
a"
)=0cc175b9c0f1b6a831c399e269772661
abc"
)=900150983cd24fb0d6963f7d28e17f72
messagedigest"
)=f96b697d7cb7938d525a2f31aaf161d0
abcdefghijklmnopqrstuvwxyz"
)=c3fcd3d76192e4007dfb496cca67e13b
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
)=
d174ab98d277d9f5a5611c2c9f419d9f
MD5("
123456789012345678901234567890123456789012345678901234567890123456789
01234567890"
)=57edf4a22be3c955ac49da2e2107b67a
MD5算法之C#程序
MD5算法比较特别,最适合用汇编语言来写,好多高级语言对之无能无力或效率极低。
比如我最开始尝试用Python和Euphoria编写,发现不太容易。
相比而言,C#作为C家簇
中新兴的一门.net语言,功能比较全面。
花了一晚上的工夫终于用C#最先实现了MD5。
主要是由于对算法的一些细节不太注意,结果输出总是不对,调试了好长时间。
[code]
//源文件:
md5.cs
//MD5Alogrithm
//byrufi2004.6.20
usingSystem;
usingSystem.Collections;
usingSystem.IO;
publicclassMD5{
//staticstatevariables
privatestaticUInt32A;
privatestaticUInt32B;
privatestaticUInt32C;
privatestaticUInt32D;
//numberofbitstorotateintranforming
privateconstintS11=7;
privateconstintS12=12;
privateconstintS13=17;
privateconstintS14=22;
privateconstintS21=5;
privateconstintS22=9;
privateconstintS23=14;
privateconstintS24=20;
privateconstintS31=4;
privateconstintS32=11;
privateconstintS33=16;
privateconstintS34=23;
privateconstintS41=6;
privateconstintS42=10;
privateconstintS43=15;
privateconstintS44=21;
/*F,G,HandIarebasicMD5functions.
*四个非线性函数:
*
*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))
*(&
与,|或,~非,^异或)
*/
privatestaticUInt32F(UInt32x,UInt32y,UInt32z){
return(x&
y)|((~x)&
z);
}
privatestaticUInt32G(UInt32x,UInt32y,UInt32z){
z)|(y&
(~z));
privatestaticUInt32H(UInt32x,UInt32y,UInt32z){
returnx^y^z;
privatestaticUInt32I(UInt32x,UInt32y,UInt32z){
returny^(x|(~z));
/*FF,GG,HH,andIItransformationsforrounds1,2,3,and4.
*Rotationisseparatefromadditiontopreventrecomputation.
privatestaticvoidFF(refUInt32a,UInt32b,UInt32c,UInt32d,UInt32mj,ints,UInt32ti){
a=a+F(b,c,d)+mj+ti;
a=a<
s|a>
>
(32-s);
a+=b;
privatestaticvoidGG(refUInt32a,UInt32b,UInt32c,UInt32d,UInt32mj,ints,UInt32ti){
a=a+G(b,c,d)+mj+ti;
privatestaticvoidHH(refUInt32a,UInt32b,UInt32c,UInt32d,UInt32mj,ints,UInt32ti){
a=a+H(b,c,d)+mj+ti;
privatestaticvoidII(refUInt32a,UInt32b,UInt32c,UInt32d,UInt32mj,ints,UInt32ti){
a=a+I(b,c,d)+mj+ti;
privatestaticvoidMD5_Init(){
A=0x67452301;
//inmemory,thisis0x01234567
B=0xefcdab89;
//inmemory,thisis0x89abcdef
C=0x98badcfe;
//inmemory,thisis0xfedcba98
D=0x10325476;
//inmemory,thisis0x76543210
privatestaticUInt32[]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=newArrayList(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)&
byteh3=(byte)((N>
16)&
byteh4=(byte)((N>
24)&
byteh5=(byte)((N>
32)&
byteh6=(byte)((N>
40)&
byteh7=(byte)((N>
48)&
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));
/*Decodesinput(byte[])intooutput(UInt32[]).Assumeslenis
*amultipleof4.
UInt32[]output=newUInt32[size/4];
for(Int64i=0,j=0;
size;
j++,i+=4){
output[j]=(UInt32)(ts[i]|ts[i+1]<
8|ts[i+2]<
16|ts[i+3]<
24);
returnoutput;
privatestaticUInt32[]MD5_Trasform(UInt32[]x){
UInt32a,b,c,d;
for(intk=0;
k<
x.Length;
k+=16){
a=A;
b=B;
c=C;
d=D;
/*Round1*/
FF(refa,b,c,d,x[k+0],S11,0xd76aa478);
/*1*/
FF(refd,a,b,c,x[k+1],S12,0xe8c7b756);
/*2*/
FF(refc,d,a,b,x[k+2],S13,0x242070db);
/*3*/
FF(refb,c,d,a,x[k+3],S14,0xc1bdceee);
/*4*/
FF(refa,b,c,d,x[k+4],S11,0xf57c0faf);
/*5*/
FF(refd,a,b,c,x[k+5],S12,0x4787c62a);
/*6*/
FF(refc,d,a,b,x[k+6],S13,0xa8304613);
/*7*/
FF(refb,c,d,a,x[k+7],S14,0xfd469501);
/*8*/
FF(refa,b,c,d,x[k+8],S11,0x698098d8);
/*9*/
FF(refd,a,b,c,x[k+9],S12,0x8b44f7af);
/*10*/
FF(refc,d,a,b,x[k+10],S13,0xffff5bb1);
/*11*/
FF(refb,c,d,a,x[k+11],S14,0x895cd7be);
/*12*/
FF(refa,b,c,d,x[k+12],S11,0x6b901122);
/*13*/
FF(refd,a,b,c,x[k+13],S12,0xfd987193);
/*14*/
FF(refc,d,a,b,x[k+14],S13,0xa679438e);
/*15*/
FF(refb,c,d,a,x[k+15],S14,0x49b40821);
/*16*/
/*Round2*/
GG(refa,b,c,d,x[k+1],S21,0xf61e2562);
/*17*/
GG(refd,a,b,c,x[k+6],S22,0xc040b340);
/*18*/
GG(refc,d,a,b,x[k+11],S23,0x265e5a51);
/*19*/
GG(refb,c,d,a,x[k+0],S24,0xe9b6c7aa);
/*20*/
GG(refa,b,c,d,x[k+5],S21,0xd62f105d);
/*21*/
GG(refd,a,b,c,x[k+10],S22,0x2441453);
/*22*/
GG(refc,d,a,b,x[k+15],S23,0xd8a1e681);
/*23*/
GG(refb,c,d,a,x[k+4],S24,0xe7d3fbc8);
/*24*/
GG(refa,b,c,d,x[k+9],S21,0x21e1cde6);
/*25*/
GG(refd,a,b,c,x[k+14],S22,0xc33707d6);
/*26*/
GG(refc,d,a,b,x[k+3],S23,0xf4d50d87);
/*27*/
GG(refb,c,d,a,x[k+8],S24,0x455a14ed);
/*28*/
GG(refa,b,c,d,x[k+13],S21,0xa9e3e905);
/*29*/
GG(refd,a,b,c,x[k+2],S22,0xfcefa3f8);
/*30*/
GG(refc,d,a,b,x[k+7],S23,0x676f02d9);
/*31*/
GG(refb,c,d,a,