2006-11-30

php和.net中的Md5函数如何兼容

最近在做一个php和.net共同组成的项目,接收.net部分传送过来的一个经md5过的数据,我惊奇的发现,居然和php进行md5的结果不同,这是为啥呢?

.net端程序是这么写的:
System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
byte[] bytesSrc = encoding.GetBytes("xutf");
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(bytesSrc);
string keyMd5=Convert.ToBase64String(result);
输入的"xutf",得出的结果是"5j1NYFDLhM9dc/XOfRwkyg=="。

php端程序是这么写的:
$keymd5=base64_encode(md5("xutf"));
同样输入"xutf",得出来的结果却是"ZTYzZDRkNjA1MGNiODRjZjVkNzNmNWNlN2QxYzI0Y2E="。

这样下去,程序没法写了,同样的操作为什么结果不同呢?

原来php的md5函数输出的结果是转换成16位表示的md5结果,而.net的md5.ComputeHash方法输出的结果是原始的md5结果。(注:php5的md5函数string md5 ( string str [, bool raw_output] )开始支持输出原始结果,参数raw_output只支持php5,但是我在使用php4)

如果想让php的结果等同于.net的结果,那么需要对md5函数的结果进行16进制字符串到标准字符串的转换。
那么php程序应改为:
$md5hex=md5("xutf");
$len=strlen($md5hex)/2;
$md5raw="";
for($i=0;$i<$len;$i++) { $md5raw=$md5raw . chr(hexdec(substr($md5hex,$i*2,2))); } $keyMd5=base64_encode($md5raw);

如果想让.net的结果等同于php的结果,那么需要把md5.ComputeHash方法输出的结果转换成16进制字符串,那么.net程序应该改为:
System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
byte[] bytesSrc = encoding.GetBytes("xutf");
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(bytesSrc);

StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.Length; i++)
sb.AppendFormat("{0:x2}", result[i]);
string s1=sb.ToString();
byte[] bytesmd5 = encoding.GetBytes(s1);
string keymd5=Convert.ToBase64String(bytesmd5);

Technorati technorati tags: , ,

请不要吝惜您的评论,每一条评论,都是我在漫漫长夜前行的力量

9 条评论:

Anonymous 匿名 说...

Tinyfool:您好!
其实这个评论应该发在《一个具体项目的重构》,但是在2006年8月份给您发了评论http://www.tinydust.net/prog/diary/2005/10/blog-post_30.html,还有给您发了更详细的Email:
.
当然,您有不回复的权利,但是我还是要请教你2个问题:
第一:文章《[埋坑计划]一个具体项目的重构(三)完结篇》中的通讯插件系统示意图如何得到,在Blog上没显示出来啊?能够给我发一张图或让它在你的Blog显示出来,谢谢!
地址:http://www.tinydust.net/prog/diary/2005/10/blog-post_30.html

第二:能否回复我给你发的Email:
tinyfool@gmail.com.

我实在不想留着问题过年啊.祝圣诞快乐了!
谢谢!
by SK
MyEmail: helpworld@163.com

10:39 上午

 
Anonymous SK 说...

用FireFox不能发表评论!

10:40 上午

 
Blogger 一米六二 说...

哈哈,大牛同志 你说反了吧?
我用php,md5输出的是32位
记得动网的asp的md5是16位,我记得

7:16 下午

 
Blogger tiny 说...

代码在这里,有啥问题你跑跑看,别想当然

11:16 下午

 
Anonymous 匿名 说...

php的md5从来就是32位的
而且不管是不是php,md5是公开的摘要算法,从来计算出的序列都是32位,生成16位的那些不能算是md5(或者叫md4.9?)了。

1:57 下午

 
Anonymous 匿名 说...

我是楼上,补充:
echo md5("xutf");//e63d4d6050cb84cf5d73f5ce7d1c24ca

1:58 下午

 
Blogger tiny 说...

本不想多解释,其实我说的很清楚,.net中md5出来的结果是一个原始字符串,但是一般来说原始字符串可能有非127内的ASCII代码,所以最后使用的时候多数会进行base64处理。然而php的md5是已经被转化为16进制ASCII代码的结果。所以,看似相似的md5+base64后的结果,并不相同

这个文章就是说明,怎么用php模拟.net的结果,或者用.net来模拟php的结果,这样可以方便的兼容对方写出来的代码

有质疑的请试图看明白再说话,觉得代码不对的自己找个运行环境跑跑然后随便批评

2:46 下午

 
Blogger 一米六二 说...

我手头没有.net环境 不然帮测一下.

1:40 下午

 
Anonymous Platinum 说...

用 PHP 内置函数会 pack 更快些

echo base64_encode(pack("H*", md5("xutf")));

出来的就是你那个 .net 的结果

我最初也是自己写循环去转,发现效率差很多,后来才知道还有 pack 这个函数

5:14 下午

 

发表评论

<< 主页