Java 与 PHP 的MD5加密为什么不一样?

cnaaa8 2014-05-20 11:14:17
php代码:


echo md5(chr(142));



java代码





import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class utils {
public static void main(String[] args) {

char ss=(char)142;//这里换成56后md5后和php版的 md5后的结果一样
System.out.println(md5(ss+""));

}


public static String md5(String plainText) {
byte[] secretBytes = null;
try {
secretBytes = MessageDigest.getInstance("md5").digest(
plainText.getBytes());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("没有md5这个算法!");
}
String md5code = new BigInteger(1, secretBytes).toString(16);
for (int i = 0; i < 32 - md5code.length(); i++) {
md5code = "0" + md5code;
}
return md5code;
}
}



经过测试 获取142的char类型的md5后数值不一样,获取56 的char 后md5的值 一样,这是怎么回事,如何解决(都是utf-8编码)
...全文
5462 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
空或灵 2016-11-10
  • 打赏
  • 举报
回复

echo 'hello';
dz215136304 2016-03-23
  • 打赏
  • 举报
回复
编码不对 换下试试
小绵羊 2014-05-23
  • 打赏
  • 举报
回复

<?php
#重要
header('Content-Type: text/html; charset=UTF-8');

function unicode_decode($unistr, $encoding = 'UTF-8', $ishex = false, $prefix = '&#', $postfix = ';') {
	$arruni = explode($prefix, $unistr);
	$unistr = '';

	for($i = 1, $len = count($arruni); $i < $len; $i++) {
		if (strlen($postfix) > 0) {
			$arruni[$i] = substr($arruni[$i], 0, strlen($arruni[$i]) - strlen($postfix));
		}
		$temp = $ishex ? hexdec($arruni[$i]) : intval($arruni[$i]);
		$unistr .= ($temp < 256) ? chr(0) . chr($temp) : chr($temp / 256) . chr($temp % 256);
	}

	return iconv('UCS-2', $encoding, $unistr);
}

#将数字转成Unicode
$s =  "\u".dechex(142);

#将Unicode转成UTF8后再计算MD5就跟Java一样了
echo md5(unicode_decode($s,'utf-8',true,'\u',''));#c18af90e0c90ea3b209bad6a3d373d82

#chr($char)函数只接受char类型参数,超出char范围的被强制向下转型,然后就没有然后了。

?>

ps.我是搞java的,php了解的不是太多,如有不妥之处,权当没看见哈哈哈哈
tony4geek 2014-05-22
  • 打赏
  • 举报
回复
怀疑是编码的问题引起的。
vnvlyp 2014-05-21
  • 打赏
  • 举报
回复
我看你的要求似乎就是两种吧 第一种是对现有字符串散列,比如你代码里的password 第二种是对字节流散列,比如那个pt 其实你在Java里可以分开处理吧,不一定要把字节流也转换为字符串啊 对于第一种,getBytes的时候用UTF-8编码 对于第二种,直接转换为byte数组,然后对数组进行散列
cnaaa8 2014-05-21
  • 打赏
  • 举报
回复
引用 8 楼 vnvlyp 的回复:
你使用的是什么字符集啊?如果只需要0~255,那么用ISO-8859-1字符编码好了 把MD5方法内改成getBytes("ISO-8859-1")
引用 8 楼 vnvlyp 的回复:
你使用的是什么字符集啊?如果只需要0~255,那么用ISO-8859-1字符编码好了 把MD5方法内改成getBytes("ISO-8859-1")
utf-8编码 ,如果不改编码 还有什么办法吗
vnvlyp 2014-05-21
  • 打赏
  • 举报
回复
你使用的是什么字符集啊?如果只需要0~255,那么用ISO-8859-1字符编码好了 把MD5方法内改成getBytes("ISO-8859-1")
cnaaa8 2014-05-21
  • 打赏
  • 举报
回复
引用 5 楼 vnvlyp 的回复:
如果非要用String,那你要保证是Java和PHP编码相同的才行啊 比如123456这种当然可以,而(char)142在两边的编码是不同的当然不行 作为密码的话,一般都只会允许标准ASCII,不包括大于127的扩展码,你不必要允许这种密码啊。。
或者我的java代码如何改下,可以实现和php一样的结果
cnaaa8 2014-05-21
  • 打赏
  • 举报
回复
引用 5 楼 vnvlyp 的回复:
如果非要用String,那你要保证是Java和PHP编码相同的才行啊 比如123456这种当然可以,而(char)142在两边的编码是不同的当然不行 作为密码的话,一般都只会允许标准ASCII,不包括大于127的扩展码,你不必要允许这种密码啊。。
那现在有什么解决办法吗,现在必须要用到127以上的了
vnvlyp 2014-05-21
  • 打赏
  • 举报
回复
如果非要用String,那你要保证是Java和PHP编码相同的才行啊 比如123456这种当然可以,而(char)142在两边的编码是不同的当然不行 作为密码的话,一般都只会允许标准ASCII,不包括大于127的扩展码,你不必要允许这种密码啊。。
cnaaa8 2014-05-21
  • 打赏
  • 举报
回复
我这里必须传入一个字符串,我把char类型字符串转成字符串再转成byte数组,同样和php的结果不一样,代码如下

char ss=(char)142;
md5((String.valueof(ss)).getBytes());
cnaaa8 2014-05-21
  • 打赏
  • 举报
回复
引用 3 楼 vnvlyp 的回复:
为什么非要传字符串。。字符串涉及到编码问题很烦的 而且142是个ASCII扩展字符,有些字符集里根本没有(你的默认字符集应该是GBK,而GBK应该是没有这个字符的) 你可以打印String.valueof(ss)).getBytes()这个数组,你会发现142被编码成乱七八糟的编码了(GBK应该编码成63)
引用 4 楼 u010541899 的回复:

  public static String getMd5(byte[] buffer) throws NoSuchAlgorithmException{
    String s  = null;
    char hexDigist[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
    MessageDigest md = MessageDigest.getInstance("MD5");
    md.update(buffer);
    byte[] datas = md.digest(); //16个字节的长整数
    char[] str = new char[2*16];
    int k = 0;
    for(int i=0;i<16;i++){
      byte b   = datas[i];
      str[k++] = hexDigist[b>>>4 & 0xf];//高4位
      str[k++] = hexDigist[b & 0xf];//低4位
    }
    s = new String(str);
    return s;
  }
java中的MD5返回的是一个128位的长整形数,即16个字节,一个字节映射成2个字符,所以就是32个字符,md5 不可能不一样的都是遵循md5协议实现的,只是PHP在底层用C语言实现了 这里测试下: java:
 public static void main(String[] args) {
    try {
      System.out.println(getMd5("123".getBytes()));
    } catch (NoSuchAlgorithmException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
输出: 202cb962ac59075b964b07152d234b70 PHP代码:
echo md5("123");
输出: 202cb962ac59075b964b07152d234b70
我把php和java代码全部贴出来吧

<?php


//php为正确的 结果:CA15B8C6D72A4442942045956DD371F8
$password="123456";
$pt='\x00\x00\x00\x00\x16\x9d\x56\x75';
$vc='!PRY';
$passwd = jspassword($password,$pt, $vc);
echo "<br>结果:".$pt."<br>".$vc."<br>密码:".$passwd."<br><br>";







function jspassword($p,$pt,$vc,$md5 = true)
{
	echo $p.":".$pt.":".$vc;
	if($md5)
	{
		$p = strtoupper(md5($p));
	}
	//echo "<br>".$p;exit;
	$len = strlen($p);
	$temp = null;
	//echo "<br>md5Password:".$p."<br>";
	for ($i=0; $i < $len ; $i = $i + 2)
	{
		//echo "<br>i:".$i;
		$temp .= '\x'.substr($p, $i,2);
	}
	//echo "<br>".$temp."<br>";
	//echo "<br><br><br>--->>>".md5(hex2asc($temp).hex2asc($pt));
	//$str=hex2asc($temp).hex2asc($pt);
	//echo "<br>内部:".$str."-->".md5(hex2asc($temp))."-->".md5(hex2asc($pt));
	return strtoupper(md5(strtoupper(md5(hex2asc($temp).hex2asc($pt))).$vc));
}

/**
 * 十六进制转字符
 * 
 * @access private
 * @param string $str
 * @return string
 */
function hex2asc($str)
{
	//echo "处理前:".$str."<br>";
	//print_r( explode('\x', $str));
	$str = join('', explode('\x', $str));
	//echo "<br>处理后:".$str;
	$len = strlen($str);
	$data = null;
	for ($i=0;$i<$len;$i+=2)
	{
		//echo "<br>::".substr($str,$i,2);
		echo "<br>".hexdec(substr($str,$i,2)).":::".chr(hexdec(substr($str,$i,2)))."->".md5(chr(hexdec(substr($str,$i,2))));
		$data.=chr(hexdec(substr($str,$i,2)));
	}
	echo "<br>".md5($data)."<br>";
	return $data;
}
?>



import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


public class utils {
	public static void main(String[] args) {
		
		utils u=new utils();
		
		String up=u.jspassword("123456", "\\x00\\x00\\x00\\x00\\x16\\x9d\\x56\\x75", "!PRY", true);
		System.out.println("-----------------------------");
		System.out.println(up);
	}
	
	
	
	public String jspassword(String password,String pt,String vc,boolean md5){
		
		if(md5)
		{
			password = utils.md5(password).toUpperCase();
		}
		int len =password.length();
		String temp="";
		
		for (int i=0; i < len ; i = i + 2)
		{
			
			
			temp += "\\x"+password.substring(i, i+2);
		}
		
		
		return (utils.md5(utils.md5(utils.hex2asc(temp)+utils.hex2asc(pt)) .toUpperCase()+vc) ).toUpperCase();
		
	}
	
	public static String hex2asc(String str){
		String [] s=str.trim().split("\\\\x");
		//System.out.println(s.length);
		StringBuffer sb=new StringBuffer();
		for(String sItem:s){
			//System.out.println(sItem);
			sb.append(sItem);
		}
		int len = sb.toString().length();
		
		//String data = null;
		StringBuffer sb1=new StringBuffer();
		
		for (int i=0;i<len;i+=2)
		{
			int x=Integer.parseInt(sb.toString().substring(i, i+2),16);
			char ss=(char) x;
			
			System.out.println(x+"::"+ss+"转换后->"+utils.md5(String.valueOf(ss)));
			
			sb1.append(String.valueOf(ss));
		}
		
		return sb1.toString();
	}
	
	public static String md5(String plainText) {
		
		
		byte[] secretBytes = null;
		try {
			secretBytes = MessageDigest.getInstance("md5").digest(
					plainText.getBytes());
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("没有md5这个算法!");
		}
		String md5code = new BigInteger(1, secretBytes).toString(16);
		for (int i = 0; i < 32 - md5code.length(); i++) {
			md5code = "0" + md5code;
		}
		return md5code;
	}
	




	

	
}

vnvlyp 2014-05-21
  • 打赏
  • 举报
回复
为什么非要传字符串。。字符串涉及到编码问题很烦的 而且142是个ASCII扩展字符,有些字符集里根本没有(你的默认字符集应该是GBK,而GBK应该是没有这个字符的) 你可以打印String.valueof(ss)).getBytes()这个数组,你会发现142被编码成乱七八糟的编码了(GBK应该编码成63)
vnvlyp 2014-05-20
  • 打赏
  • 举报
回复
Java和PHP解码不同吧
	public static String md5(byte[] bys) {
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(bys);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有md5这个算法!");
        }
        String md5code = new BigInteger(1, secretBytes).toString(16);
        for (int i = 0; i < 32 - md5code.length(); i++) {
            md5code = "0" + md5code;
        }
        return md5code;
    }
你把这个方法像上面那样改成接受byte数组的,然后你这样调用
System.out.println(md5(new byte[] {(byte)142}));
结果应该是和PHP一样的

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧