通用网络版本md5算法和.net中md5算法接轨 (转)

前两天写了一个接口验证的程序,和老的asp代码对接,结果发现验证出错了。于是花了几个小时对.net中md5用法顺便把相关的一些编码、类型转化进行一点总结。旨在抛砖引玉。
首先我在这里对 md5 算法做一个简要的介绍:它全称是Message-Digest Algorithm 5,在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明,经有MD2、MD3和MD4几个低级版本。Message-Digest即信息摘要,泛指把字节串(Message)的进行Hash变换,结果是把一个任意长度的字节串变换成一定长的大整数。按照原算法的描述,md5是一个不可逆的算法,所谓的不可逆就是没有解密函数,而且存在极小概率的:多对一情况,即使我们通常验证也是用:md5(x)=md5(y)这样的方式来验证,而不是用破解函数,破解后验证原码。也因此对md5的破译的方法常为穷举法,就是算出所有的可能值然后对比,按照这种方法一个8位密码,可能有52(字母)+10(数字)+()=)20(多个特殊符号,有的可能限制作为密码)组成,这样就有大约P(82,8)= 1437064076448000 种可能,P4级别的机器,估计需要连续作战1百多万年才能全部对比完一次。除了有一定的安全性外,最值得一提的是md5算法的使用不需要支付任何版权的费用,这无疑也是最喜欢共享的兄弟们来说也是最想看到的一点。
具体算法我就不再这里罗嗦了,网上很多都有说明。
接下来说网上常用的asp 加密的vbscript 写的md5 算法和.net 算法写法。Asp 的加密算法网上很多,但传来传去都是一个版本,我附在代码中供参考:该算法通常会产生一个:长度为32 的16 进制的数据串,其中a-f 为小写。
和该asp 程序对应,我写了一个c# 的直接把字符串类型数据,经md5 运算后也返回字符串格式的数据。程序如下[ 例一] ;
……// 这里省略了系统自动引用名称空间(namespace )
using System.Text;
using System.Security.Cryptography;
// 这里的类名,以及名称空间之类的系统自动加的东西省略。
public string AsciibitLow(encypStr)
         {
              string retStr;
              MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();
// 创建md5对象
             byte[] inputBye;
              byte[] outputBye;
              inputBye = Encoding.ASCII.GetBytes(encypStr);
// 使用ascii编码方式把字符串转化为字节数组.
              outputBye = m5.ComputeHash(inputBye);
               retStr = System.BitConverter.ToString(outputBye);
              retStr = retStr.Replace("-", "").ToLower();
               return (retStr);
        }
[ 程序说明:]
第一、              看到这里只是为了copy代码的使用的兄弟们就不必浪费时间了。上面代码在win2003+.net2.0+vs2005测试没有问题。在.net1.1的框架中没有测试,但和本文相关应用部分.net1.1和net2.0没有多大区别,应该可以直接copy。强烈建议实际测试后使用。
第二、              System.Text ,System.Security.Cryptography无论是在winform,控制台程序还是网页程序中都必须加载的两个名称空间(namespace)前者提供了Encoding编码转化转化的方法,后者则是md5等其他加密相关算法namespace。
第三、              由于系统体统提供的计算 md5 ComputeHash 算法中,输入输出都是字节数组,所以在这里用了不同的数据类型转化方式,把字节数组中的数据转化为字符串输出。值得一提的是不同的编码方式,和不同的类型转化方式的结果不同。这就是稍后要讨论的内容。
第四、              retStr.Replace("-", "").ToLower() 这一步算作是把运算结果,计算到和常用的asp中的md5算法具有相同加密结果的一步,本来可以写成System.BitConverter.ToString(outputBye) .Replace("-", "").ToLower()一步到位。想想第一太长,第二习惯vbs的兄弟们不习惯。总的来说其功能就是把BitConverter转化为形如“68-5C-FA”的字符串转化为“685cfa”的asp标准格式的字符串。
好了接下的部分我以c#的语法,简要介绍不同编码方式,以及不同类型转化方式给所带来的不同结果,以及对产生该结果的原因做一个简要的说明。稍后的内容要用下面的例子作为模板,实际应用时引用的全部名称空间同例一。
[ 例二]
public string AsciibitLow(encypStr)
         {
              string retStr;
              MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();
              byte[] inputBye;
              byte[] outputBye;
              inputBye = Encoding.ASCII.GetBytes(encypStr);
              outputBye = m5.ComputeHash(inputBye);
retStr = Convert.ToBase64String(outputBye);
               return (retStr);
        }
看上面的例子,标红色的部分: inputBye行(以后简称 i行)是把字符串进行相应的asc编码并返回对应的字节数组的过程, retStr行(以后简称 r行)把加密后的字节数组数据转化为字符串。这里通过不同的i,r行的不同,来观测其计算结果。稍后的例子中会都以字符串:“dfd!@$%127”作为输入的原码。
上面的[例二]返回的结果是: 8j4uZKfJ2f3xH5ex12dPoQ==    
值得一提是:当i 行 inputBye = Encoding.UTF8.GetBytes(encypStr);
的时候,其加密结果和 [例二]返回值都是: 8j4uZKfJ2f3xH5ex12dPoQ==    。
[例三 ]
修改 i,r行如下:
              inputBye = Encoding.Unicode.GetBytes(this.encypStr);
// 使用Unicode编码方式把字符串转化为字节数组.
               retStr = Converter.ToBase64String (outputBye);
返回的结果是: Df9jwdVIr6bba4PKXTig2w==
这里不同的编码方式, utf8,ascii,unicode返回的数值不同,原因比较简单,前二者都是位编码的所以结果一致;后者unicode是双字节编码格式,导致在字符串转化为字节数组的时候出现了不同的结果。
 [ 例四]相对上面例子,对加密后结果使用了不同的类型转化方式。
inputBye = Encoding.ASCII.GetBytes(encypStr);
retStr = System.BitConverter.ToString(outputBye)
返回的结果是: F2-3E-2E-64-A7-C9-D9-FD-F1-1F-97-B1-D7-67-4F-A1
inputBye = Encoding. Unicode.GetBytes(encypStr);
retStr = System.BitConverter.ToString(outputBye)
返回的结果是: 0D-FF-63-C1-D5-48-AF-A6-DB-6B-83-CA-5D-38-A0-DB
       
可以看到的一个结果:这里把 md5计算后的结果用不同的转化类,转化为字符串数据的时候出现的结果也不相同,这里我就要把: Converter.ToBase64String System.BitConverter.ToString 作一个区分。
其中:
另外大家很惊讶的是:即使到了这里得到的“F2-3E-2E-64-A7-C9…… ”,依旧不是我们想要的结果。是呀,如果可以把“-”号去掉,大写字母转化为小写字母,你就大悟了。
看到这里,大家一定明白了,网上那个vbscript的md5只是在ascii/utf8编码后,进行md5运算,最后使用基本类型转化并去掉 “-”符号的小写的形式的字符串格式而已。在感受到.net的变化无穷的时候,和使用别人东西无奈的时候,你一定又想起了vbs的自由。算了自己写个函数来转化算了,省得到了最后一步功亏一篑。好,这里就献上看到的一位兄弟写的把加密后的byte数组转化为string的语句。
[例五]
          string retStr = “”;
MD5 md5 = MD5.Create(); // 这里是另一种创建md5对象方法     
        byte[] s = md5.ComputeHash(Encoding.Unicode.GetBytes(inputBye));
        for (int i = 0; i < s.Length; i++)
        {
            // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写( X )则格式后的字符是大写字符
            retStr = retStr + s[i].ToString("x");
        }
       看到这里都感觉一定不错了,但是你知道这里有问题吗?这也是我cp到的第一个程序测试的时候,99%时候可以正常,但偶尔有失败的情况,跟踪调试后发现 s[i].ToString("x")这里出问题了。很多时候这里把0x0忽略掉了,返回的数据很多时候不是标准的32位了,而是<=32位。
写 asp的老兄弟们总是比较难接受C#的,然而它强大的类型检验,可配置,可重用性,编译后的快速度,状态保留,页面调试都诱惑着我们……难,并不可怕,可怕的是知难而退。
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值