java生成文件md5十六进制串并和校验码比对以及md5算法的解疑释惑

编程入门 行业动态 更新时间:2024-10-24 12:31:42

java生成文件md5十六进制串并和校验码比对以及md5算法的<a href=https://www.elefans.com/category/jswz/34/1728201.html style=解疑释惑"/>

java生成文件md5十六进制串并和校验码比对以及md5算法的解疑释惑

网上下载文件的时候,常常看到会有各种校验值,比如我去现在apache,就可以看到下面的样子:

点击去之后可以得到一串密文“b8d8d49d8178734124c4ff6f3a409d3d”,这串密文的作用就是验证下载的文件是否安全,当下载的文件经过了修改之后得到的值就和官方网站公布的md5串不一致了,以此来校验下载的文件是否是安全且没有经过任何篡改的。

我现在就把这个文件下载下来了,放在了"d:\\zhao\\tmp\\apache-maven-3.5.2-bin.zip"这个位置,关键是我怎么计算自己下载的文件的md5串呢,当然,网上有很多工具的,可以自行百度下载。但是我还想自己一探究竟,起码要验证下自己的想法才肯罢休,于是乎就有了下面的java代码。

package com.zhao.fraud.test;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import org.junit.Test;
public class AppTest {@Testpublic void testFileMd5(){FileInputStream fis=null;try {  MessageDigest md5 = MessageDigest.getInstance("MD5");  fis=new FileInputStream("d:\\zhao\\tmp\\apache-maven-3.5.2-bin.zip");byte[] buff = new byte[1024];int len=0;while((len=fis.read(buff))!=-1){md5.update(buff,0,len);}byte[] retBytes = md5.digest();  String md5str = parseByte2HexStr(retBytes);  System.out.println(md5str);} catch (Exception e) {  e.printStackTrace();}  finally{if (fis!=null) {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}}//把字节数组转成16进制字符串private  String parseByte2HexStr(byte buf[]) {  StringBuffer sb = new StringBuffer();  int length = buf.length;for (int i = 0; i < length; i++) {  String hex = Integer.toHexString(buf[i]&0xFF);  if (hex.length() == 1) {  hex = '0' + hex;  }  sb.append(hex.toUpperCase());  }  return sb.toString();  } 
}

运行,得到结果:

因为我在parseByte2HexStr()函数中把十六进制字符串转为大写了,所以这里是大写,仔细比较一下我自己得到的值和网上公布的md5检验码可以发现是完全一致的。而当我把里面的文件随便修改一下,得到了一个“10CDBC4AD24C2B9F510882D66FA00CB9”,再修改,又变了,所以这就是自己写java程序和校验码比对的全部过程了。

既然用到了md5,就再详细说下md5。

什么是md5?

        Message Digest Algorithm 5 简称md5,即消息摘要算法第五版。

java里面的md5算法最终应该返回什么?

        md5我们又叫做md5字符串,自然是返回字符串了,java里面通过MessageDigest对象来计算md5的值,返回字节数组byte[]。字节数组怎么转为字符串呢,我们知道每个字节(byte)在java里面占有8位(bit),可以分成两个4位来看,因为一个4位最大也就是“1111”,所以一个字节正好可以用两个十六进制的字符来表示,比如"1111"就可以转变为十六进制的"f”。所以,结论就是,java里面的md5算法最终应该返回十六进制的字符串,这不是强制的,却是很好的解决办法。这也是为什么我们学md5就写md5吗,为什么总是还要牵涉到字节数组怎么转化为十六进制字符串的原因。

java里面的md5算法最终应该返回的十六进制字符串的长度?

        不管用md5加密什么,一个2G的文件也好,一个“a”也罢,java里面最终返回的都是字节数组byte[],而且这个字节数组byte[]的长度总是16,也就是返回值总是占有128位,按照每4位可以转为一个十六进制的字符串的规则,这128位(bit)对应着32个十六进制的字符,好,一般而言,这经过字节数组byte[]转换而来的32个十六进制字符就是我们要返回的东西了。为什么说一般而言,因为有时候你还会见到只有8个十六进制字符的md5串,你要知道它只是把上面得到的32个十六进制字符截取了一下罢了。

怎么把字节数组byte[]转为十六进制字符串?

        这个方法有很多,所以你可能看到网上如果搜素java里面的md5算法的时候,有可能看到这一篇是如此写,那一篇却又换了一个写法,你心里可能会犯嘀咕,是不是有一个不对啊,还很有可能为此而不知如何抉择,一头雾水的情况下索性不看了。这里要告诉你,方法自己很多种,只要能转换成功就可以。

说了这么多,该怎么写呢?干货来了:

package com.lzzcms.utils;
import java.security.MessageDigest;
public class CryptoUtilTest {public static String parseByte2HexStr(byte buf[]) {  StringBuffer sb = new StringBuffer();  int length = buf.length;for (int i = 0; i < length; i++) {  //toHexString参数时十进制的整数,与十六进制0xFF做与运算,是为了//确保真正存储的补码一致String hex = Integer.toHexString(buf[i]&0xFF);  if (hex.length() == 1) {  //如toHexString(15),就返回一个“f”,这里为了确保每个byte都能转为两个十六进制字符hex = '0' + hex;  }  sb.append(hex.toUpperCase());  }  return sb.toString();  } public static String getMD5(String content) {  String md5str = "";  try {  // 1 创建一个提供信息摘要算法的对象,初始化为md5算法对象  MessageDigest md = MessageDigest.getInstance("MD5");  // 2 得到要加密内容的byte数组  byte[] contentBytes = content.getBytes();  /* 3 计算后获得字节数组,返回值总是128个bit,即16个byte当要处理的内容contentBytes可以一次性获得的时候,可以用md.digest(contentBytes)来代替md.update(contentBytes);byte[] buff = md.digest()*/byte[] buff = md.digest(contentBytes);  //相当于上面的md.digest(contentBytes)
//            md.update(contentBytes);
//            byte[] buff = md.digest();  System.out.println(buff.length);//16个字节System.out.println(new String(buff));//乱码// 4 把数组buff中每一字节(一个字节占八位)换成16进制字符最终连成md5字符串  md5str = parseByte2HexStr(buff);  } catch (Exception e) {  e.printStackTrace();}  return md5str;  }  public static void main(String[] args) throws Exception {String md5 = getMD5("abcd_zhao");System.out.println(md5);}
}

运行结果:

16
+��/C�~Z�~���R�
2B19939D2F43F57E5AF57EF7ECC252E1

注意点:

    1.需要注意的地方我已经写在了注释里,注意看注释

    2.上边是加密一个短的字符串,关于加密相当长的字符串或者加密一个文件时可以分多次加密,调用MessageDigest对象的update方法即可,需要的时候可以使用update的重载方法update(input, offset, len);

当要处理的内容contentBytes可以一次性获得的时候,也可以用md.digest(contentBytes)来代替md.update(contentBytes);byte[] buff = md.digest()。

    3.digest()方法是MessageDigest对象最终对内容进行md5加密的函数,而update方法是用于获取要加密的内容。

更多推荐

java生成文件md5十六进制串并和校验码比对以及md5算法的解疑释惑

本文发布于:2024-03-10 14:15:03,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1728206.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:解疑释惑   算法   比对   校验码   文件

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!