再谈MD5

实习的第一天,项目经理给了个小问题,我这个C#的MD5加密算法出来的结果只有31位,有时也有32位,你用java实现一下,也必须要有31位或者32位的情况。好吧,仔细分析了下31位结果产生的原因,当8位的字节进行16进制转换时,如果前面四位产生的结果为0,那么后面最后的结果可能就把0省略掉了,也就是0X0A会变成0XA。其实内心是崩溃的,输出成标准的32位不是最好的吗?好吧,还是来整理一下。
先看一下项目经理给的C#代码:
 public static string MD5Encryption(string source, string key)
        {
            string temp = source + key;
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] fromData = System.Text.Encoding.Unicode.GetBytes(temp);
            byte[] targetData = md5.ComputeHash(fromData);
            string byte2String = null;
            for (int i = 0; i < targetData.Length; i++)
            {
                byte2String += targetData[i].ToString("x");
            }
            return byte2String;
        }
现在的目标情况是,需要把它翻译成java代码,代码如下:
/**
  * MD5加密
  * @param str
  * @return 
  */
 public static String encrypt(String source ,String key){
        //输入字符串
  String str = source + key;
  //返回字符串
  String str_return = null;
  try {
   
  MessageDigest md = MessageDigest.getInstance("MD5");
  //依据数组的编码方式得到待加密的数组,注意编码方式,你的可能会有不同
  byte[]byte_temp=str.getBytes("UTF-16LE");
  
  md.update(byte_temp);  
  
  byte b[] = md.digest();
  //进行转换
  str_return = byte2hex(b);
  
  } catch (Exception e){
  }
  
  return str_return;
 }

/**
     *
     * @param b
     * @return
     */
    public static String byte2hex(byte[] b) {
  //进行二进制转16进制后返回的字符串
     String hs = ""; 
     //进行单个字节进行转换的局部字符串
     String stmp = ""; 
     //迭代进行转换
     for (int n = 0; n < b.length; n++) { 
        //对于数组中每个元素进行转换得到16进制编码
        stmp = (Integer.toHexString(b[n] & 0XFF));
        //转换后添加到返回字符串末尾
        hs += stmp;        
      } 
     return hs.toLowerCase();
    }
这样产生的结果就跟C#代码一样的了。
但是这样其实是不好的,我们更想要一些标准的结果:32位的。
采用如下的方法就好了:
public static String getMD5(String str) {
byte[] source = str.getBytes();
String s = null;
char hexDigits[] = {     
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',  'e', 'f'}; 
try
{
java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" );
md.update( source );
byte tmp[] = md.digest();         

char str[] = new char[16 * 2];   
int k = 0;                               
for (int i = 0; i < 16; i++) {         
byte byte0 = tmp[i];                
str[k++] = hexDigits[byte0 >>> 4 & 0xf];  
str[k++] = hexDigits[byte0 & 0xf];            
}

s = new String(str);                        

}catch( Exception e ){
e.printStackTrace();
}
但是在这里,一定要注意理解
str[k++] = hexDigits[byte0 >>> 4 & 0xf];  
str[k++] = hexDigits[byte0 & 0xf];    
的含义是什么。第一句的意思是取字节的左四位然后转换成16进制,第二句话的意思是后四位再转换成16进制。
这样就好理解了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值