MD5作为一种散列算法,广泛用于密码传输过程中的“加密”(引号的意思是这并不是真正的加密,而是形成密码的散列值)过程。MD顾名思义Message Digest(报文摘要),可以将输入的密码,一般来说为一个字符串,进行HASH(这里简称为加密,其实是报文摘要),并且这个HASH值是单向的,理论上说是不能反向破解(“解密”)的,当然个别网站通过搜集大家简单的字符串输入形成所谓的“数据字典”,然后根据大家习惯,进行破解,这个其实就是统计形成的结果,通过比对实现,与MD5算法的理论基础没有太大的关系。最近几年,山东一个高校的女博士也在研究MD5算法的破解,并且通过一些算法可以求解密文的明文,但仅仅局限于简单的字符串。所以,目前来说,MD5的算法还是单向的,不可逆推。具体大家可以参考博文:http://www.williamlong.info/archives/1882.html
一般来说,对于未经处理的密码传输,“黑客”有两种方式获得你的密码,一种是传输拦截,一种是攻击服务器,不管哪种都能获取指定用户的密码。通过MD5算法HASH后,即使黑客截取了用户的密码,也不能破解(HASH单向)。另外,大家会纠结一个问题,既然MD5算法不能反向破解,也就不能验证(假设成立),对于密码HASH来说还有什么作用呢?用户登录账户一般来说是通过和服务器比对账户和密码来决定是否具有权限登录的,密码HASH值保存在服务器数据库,下次用户再次输入密码就进行HASH值比对就行了。
这样就遇到一个问题,万一用户的密码丢失了,用户岂不是找不回原来的密码?是的,这时候一般的网站做法是用别的途径进行身份验证(例如:手机号等),然后进行密码重置。那为什么网站会提示新密码不能和原密码相同,其实这也就是进行密码HASH值比对的结果。
需要说明的是,MD5算法,更多的用处是形成报文摘要,经私钥加密后进行数字签名,这个是公钥加密体系中的内容,感兴趣也可以了解一下。
以下是MD5算法在.NET平台下的实现:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Security.Cryptography; 5 using System.Text; 6 7 namespace MD5Encrypted 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //加密123 14 //MD5网站上给出的加密结果:202cb962ac59075b964b07152d234b70 15 string s = GetMD5("123"); 16 Console.WriteLine("123MD5加密值:" + s); 17 Console.ReadKey(); 18 } 19 public static string GetMD5(string str) 20 { 21 //创建MD5对象 22 MD5 md5 = MD5.Create(); 23 24 //开始加密 25 26 //需要将字符串转换成字节数组 27 byte[] buffer = Encoding.UTF8.GetBytes(str); 28 29 //返回一个加密好的字节数组 30 byte[] MD5Buffer= md5.ComputeHash(buffer); 31 32 /*字节数组装换成字符串的三种格式 33 将字节数组中的而每个元素按照指定的编码格式解析成字符串 34 * 直接将数组toString(); 189 123 645--- 我爱你 35 * 将字节数组中的每个元素toString() . 36 * 37 */ 38 39 40 //将字节数组转换成字符串 41 //return Encoding.UTF8.GetString(MD5Buffer); 42 43 string strNew = ""; 44 for (int i = 0; i < MD5Buffer.Length; i++) 45 { 46 strNew += MD5Buffer[i].ToString("x2"); //将十进制字符串转换成16进制 47 } 48 return strNew; 49 } 50 } 51 }
关于以上的代码需要解释的几个地方:
1、关于字节数组转换成字符串在MD5算法实现过程中会引起的问题。
因为如代码中所说字节数组转换成字符串一般有三种形式。然而对于在计算机中存储的都是二进制,对于一串二进制数可以表示一串汉字、一串英文字符等,那么字节数组的每个字节的解释就会不一样,所以这时候要注意。
2、strNew += MD5Buffer[i].ToString("x2");对于该句,toString的用法大家可以查一下API。其中的“x”表示16进制。其中“x”和“x2”的区别就在于,对于0x01,“x”解释出来的是0x1;而“x2”解释出来的是0x01;
ToString("X2") 为C#中的字符串格式控制符
X为 十六进制
2为 每次都是两位数
比如 0x0A ,若没有2,就只会输出0xA
假设有两个数10和26,正常情况十六进制显示0xA、0x1A,这样看起来不整齐,为了好看,可以指定"X2",这样显示出来就是:0x0A、0x1A。
参考网址:http://www.cnblogs.com/kuang906/articles/2301361.html