在C#中实现md5.docx
《在C#中实现md5.docx》由会员分享,可在线阅读,更多相关《在C#中实现md5.docx(21页珍藏版)》请在冰豆网上搜索。
在C#中实现md5
在C#中实现MD5加密
一:
关于MD5加密
MD5的全称是Message-DigestAlgorithm5(中文名为消息摘要算法第五版),它用以提供消息的完整性保护。
MD5用的是哈希函数,是计算机网络中应用较多的不可逆加密算法。
在非绝密应用领域甚至绝密领域内,MD5都算得上是一种非常优秀的中间技术。
MD5在90年代初由MIT的计算机科学实验室和RSADataSecurityInc发明,经MD2、MD3和MD4发展而来。
它的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数),MD5最广泛被用于各种软件的密码认证和钥匙识别上。
通俗的讲就是人们讲的序列号。
Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的“字节串”变换成一定长的大整数,这种变换只与字节的值有关,与字符集或编码方式无关。
MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。
可以看出MD5加密是无法进行解密的(也不是绝对的),例如一个string,利用MD5算法进行加密以后你是无法将他还原为原来的string。
MD5不能被解密也不是没用的,因为如果数据没有采用任何加密算法进行加密的话,数据的存储方式是以明文形式存放的,意味着数据有很大能被泄露,但是如果数据经过加密,所看到的也只是一堆毫无排列顺序可言的数字或字符。
MD5加密还有一个特点,就是同一个string在同样的编码方式下加密的结果是一样的,所以可以为任何文件(不管其大小、格式、数量)产生一个同样独一无二的“数字指纹”,如果任何人对文件做了任何改动,其MD5值也就是对应的“数字指纹”都会发生变化。
对MD5算法简要的叙述可以为:
MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
在MD5算法中,首先需要对信息进行填充,使其位长对512求余的结果等于448。
因此,信息的位长(BitsLength)将被扩展至N*512+448,即N*64+56个字节(Bytes),N为一个正整数。
填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。
然后,在这个结果后面附加一个以64位二进制表示的填充前信息长度。
经过这两步的处理,现在的信息的位长=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍。
这样做的原因是为满足后面处理中对信息长度的要求。
二:
C#下的MD5加密实现
MD5中有四个32位被称作链接变量(ChainingVariable)的整数参数,他们分别为:
A=0x01234567,B=0x89abcdef,C=0xfedcba98,D=0x76543210。
当设置好这四个链接变量后,就开始进入算法的四轮循环运算。
循环的次数是信息中512位信息分组的数目。
将上面四个链接变量复制到另外四个变量中:
A到a,B到b,C到c,D到d。
主循环有四轮(MD4只有三轮),每轮循环都很相似。
第一轮进行16次操作。
每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。
再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。
最后用该结果取代a、b、c或d中之一。
以下的例子:
(用的四轮循环)
usingSystem;
usingSystem.Text;
namespaceEncrypter
{
publicclassMD5
{
constintBITS_TO_A_BYTE=8;
constintBYTES_TO_A_WORD=4;
constintBITS_TO_A_WORD=32;
privatestaticlong[]m_lOnBits=newlong[30+1];
privatestaticlong[]m_l2Power=newlong[30+1];
privatestaticlongLShift(longlValue,longiShiftBits)
{
longLShift=0;
if(iShiftBits==0)
{
LShift=lValue;
returnLShift;
}
else
{
if(iShiftBits==31)
{
if(Convert.ToBoolean(lValue&1))
{
LShift=0x80000000;
}
else
{
LShift=0;
}
returnLShift;
}
else
{
if(iShiftBits<0||iShiftBits>31)
{
}
}
}
if(Convert.ToBoolean((lValue&m_l2Power[31-iShiftBits])))
{
LShift=((lValue&m_lOnBits[31-(iShiftBits+1)])*m_l2Power[iShiftBits])|0x80000000;
}
else
{
LShift=((lValue&m_lOnBits[31-iShiftBits])*m_l2Power[iShiftBits]);
}
returnLShift;
}
privatestaticlongRShift(longlValue,longiShiftBits)
{
longRShift=0;
if(iShiftBits==0)
{
RShift=lValue;
returnRShift;
}
else
{
if(iShiftBits==31)
{
if(Convert.ToBoolean(lValue&0x80000000))
{
RShift=1;
}
else
{
RShift=0;
}
returnRShift;
}
else
{
if(iShiftBits<0||iShiftBits>31)
{
//Err.Raise6;
}
}
}
RShift=(lValue&0x7FFFFFFE)/m_l2Power[iShiftBits];
if(Convert.ToBoolean((lValue&0x80000000)))
{
RShift=(RShift|(0x40000000/m_l2Power[iShiftBits-1]));
}
returnRShift;
}
privatestaticlongRotateLeft(longlValue,longiShiftBits)
{
longRotateLeft=0;
RotateLeft=LShift(lValue,iShiftBits)|RShift(lValue,(32-iShiftBits));
returnRotateLeft;
}
privatestaticlongAddUnsigned(longlX,longlY)
{
longAddUnsigned=0;
longlX4=0;
longlY4=0;
longlX8=0;
longlY8=0;
longlResult=0;
lX8=lX&0x80000000;
lY8=lY&0x80000000;
lX4=lX&0x40000000;
lY4=lY&0x40000000;
lResult=(lX&0x3FFFFFFF)+(lY&0x3FFFFFFF);
if(Convert.ToBoolean(lX4&lY4))
{
lResult=lResult^0x80000000^lX8^lY8;
}
elseif(Convert.ToBoolean(lX4|lY4))
{
if(Convert.ToBoolean(lResult&0x40000000))
{
lResult=lResult^0xC0000000^lX8^lY8;
}
else
{
lResult=lResult^0x40000000^lX8^lY8;
}
}
else
{
lResult=lResult^lX8^lY8;
}
AddUnsigned=lResult;
returnAddUnsigned;
}
privatestaticlongmd5_F(longx,longy,longz)
{
longmd5_F=0;
md5_F=(x&y)|((~x)&z);
returnmd5_F;
}
privatestaticlongmd5_G(longx,longy,longz)
{
longmd5_G=0;
md5_G=(x&z)|(y&(~z));
returnmd5_G;
}
privatestaticlongmd5_H(longx,longy,longz)
{
longmd5_H=0;
md5_H=(x^y^z);
returnmd5_H;
}
privatestaticlongmd5_I(longx,longy,longz)
{
longmd5_I=0;
md5_I=(y^(x|(~z)));
returnmd5_I;
}
privatestaticvoidmd5_FF(reflonga,longb,longc,longd,longx,longs,longac)
{
a=AddUnsigned(a,AddUnsigned(AddUnsigned(md5_F(b,c,d),x),ac));
a=RotateLeft(a,s);
a=AddUnsigned(a,b);
}
privatestaticvoidmd5_GG(reflonga,longb,longc,longd,longx,longs,longac)
{
a=AddUnsigned(a,AddUnsigned(AddUnsigned(md5_G(b,c,d),x),ac));
a=RotateLeft(a,s);
a=AddUnsigned(a,b);
}
privatestaticvoidmd5_HH(reflonga,longb,longc,longd,longx,longs,longac)
{
a=AddUnsigned(a,AddUnsigned(AddUnsigned(md5_H(b,c,d),x),ac));
a=RotateLeft(a,s);
a=AddUnsigned(a,b);
}
privatestaticvoidmd5_II(reflonga,longb,longc,longd,longx,longs,longac)
{
a=AddUnsigned(a,AddUnsigned(AddUnsigned(md5_I(b,c,d),x),ac));
a=RotateLeft(a,s);
a=AddUnsigned(a,b);
}
privatestaticlong[]ConvertToWordArray(stringsMessage)
{
long[]ConvertToWordArray=null;
intlMessageLength=0;
intlNumberOfWords=0;
long[]lWordArray=null;
intlBytePosition=0;
intlByteCount=0;
intlWordCount=0;
constintMODULUS_BITS=512;
constintCONGRUENT_BITS=448;
lMessageLength=sMessage.Length;
lNumberOfWords=(((lMessageLength+((MODULUS_BITS-CONGRUENT_BITS)/BITS_TO_A_BYTE))/(MODULUS_BITS/BITS_TO_A_BYTE))+1)*(MODULUS_BITS/BITS_TO_A_WORD);
lWordArray=newlong[lNumberOfWords];
lBytePosition=0;
lByteCount=0;
while(lByteCount{
lWordCount=lByteCount/BYTES_TO_A_WORD;
lBytePosition=(lByteCount%BYTES_TO_A_WORD)*BITS_TO_A_BYTE;
lWordArray[lWordCount]=lWordArray[lWordCount]|LShift(Convert.ToByte(sMessage.Substring(lByteCount,1).ToCharArray()[0]),lBytePosition);
lByteCount=lByteCount+1;
}
lWordCount=lByteCount/BYTES_TO_A_WORD;
lBytePosition=(lByteCount%BYTES_TO_A_WORD)*BITS_TO_A_BYTE;
lWordArray[lWordCount]=lWordArray[lWordCount]|LShift(0x80,lBytePosition);
lWordArray[lNumberOfWords-2]=LShift(lMessageLength,3);
lWordArray[lNumberOfWords-1]=RShift(lMessageLength,29);
ConvertToWordArray=lWordArray;
returnConvertToWordArray;
}
privatestaticstringWordToHex(longlValue)
{
stringWordToHex="";
longlByte=0;
intlCount=0;
for(lCount=0;lCount<=3;lCount++)
{
lByte=RShift(lValue,lCount*BITS_TO_A_BYTE)&m_lOnBits[BITS_TO_A_BYTE-1];
WordToHex=WordToHex+(("0"+ToHex(lByte)).Substring(("0"+ToHex(lByte)).Length-2));
}
returnWordToHex;
}
privatestaticstringToHex(longdec)
{
stringstrhex="";
while(dec>0)
{
strhex=tohex(dec%16)+strhex;
dec=dec/16;
}
returnstrhex;
}
privatestaticstringtohex(longhex)
{
stringstrhex="";
switch(hex)
{
case10:
strhex="a";break;
case11:
strhex="b";break;
case12:
strhex="c";break;
case13:
strhex="d";break;
case14:
strhex="e";break;
case15:
strhex="f";break;
default:
strhex=hex.ToString();break;
}
returnstrhex;
}
publicstaticstringEncrypt(stringsMessage,intstype)
{
stringMD5="";
for(inti=0;i<=30;i++)
{
m_lOnBits=Convert.ToInt64(Math.Pow(2,i+1)-1);
m_l2Power=Convert.ToInt64(Math.Pow(2,i));
}
long[]x=null;
intk=0;
longAA=0;
longBB=0;
longCC=0;
longDD=0;
longa=0;
longb=0;
longc=0;
longd=0;
constintS11=7;
constintS12=12;
constintS13=17;
constintS14=22;
constintS21=5;
constintS22=9;
constintS23=14;
constintS24=20;
constintS31=4;
constintS32=11;
constintS33=16;
constintS34=23;
constintS41=6;
constintS42=10;
constintS43=15;
constintS44=21;
x=ConvertToWordArray(sMessage);
a=0x67452301;
b=0xEFCDAB89;
c=0x98BADCFE;
d=0x10325476;
for(k=0;k{
AA=a;
BB=b;
CC=c;
DD=d;
//第一轮循环左移开始
md5_FF(refa,b,c,d,x[k+0],S11,0xD76AA478);
md5_FF(refd,a,b,c,x[k+1],S12,0xE8C7B756);
md5_FF(refc,d,a,b,x[k+2],S13,0x242070DB);
md5_FF(refb,c,d,a,x[k+3],S14,0xC1BDCEEE);
md5_FF(refa,b,c,d,x[k+4],S11,0xF57C0FAF);
md5_FF(refd,a,b,c,x[k+5],S12,0x4787C62A);
md5_FF(refc,d,a,b,x[k+6],S13,0xA8304613);
md5_FF(refb,c,d,a,x[k+7],S14,0xFD469501);
md5_FF(refa,b,c,d,x[k+8],S11,0x698098D8);
md5_FF(refd,a,b,c,x[k+9],S12,0x8B44F7AF);
md5_FF(refc,d,a,b,x[k+10],S13,0xFFFF5BB1);
md5_FF(refb,c,d,a,x[k+11],S14,0x895CD7BE);
md5_FF(refa,b,c,d,x[k+12],S11,0x6B901122);
md5_FF(refd,a,b,c,x[k+13],S12,0xFD987193);
md5_FF(refc,d,a,b,x[k+14],S13,0xA679438E);
md5_FF(refb,c,d,a,x[k+15],S14,0x49B40821);
//第二轮左移开始
md5_GG(refa,b,c,d,x[k+1],S21,0xF61E2562);
md5_GG(refd,a,b,c,x[k+6],S22,0xC040B340);
md5_GG(refc,d,a,b,x[k+11],S23,0x265E5A51);
md5_GG(refb,c,d,a,x[k+0],S24,0xE9B6C7AA);
md5_GG(refa,b,c,d,x[k+5],S21,0xD62F105D);
md5_GG(refd,a,b,c,x[k+10],S22,0x2441453);
md5_GG(refc,d,a,b,x[k+15],S23,0xD8A1E681);
md5_GG(refb,c,d,a,x[k+4],S24,0xE7D3FBC8);
md5_GG(refa,b,c,d,x[k+9],S21,0x21E1CDE6);
md5_GG(refd,a,b,c,x[k+14],S22,0xC33707D6);
md5_GG(refc,d,a,b,x[k+3],S23,0xF4D50D87);
md5_GG(refb,c,d,a,x[k+8