前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >计算文件Checksum的几种方法

计算文件Checksum的几种方法

作者头像
孟君
发布2019-08-26 17:53:07
9.5K0
发布2019-08-26 17:53:07
举报

回忆一下,自己是否在网站上下载文件时看到过Checksum这个东西,一串字符串?

比如,我们到Apache网站上去下载用于操作Excel的依赖包 - Apache POI,就可以看到checksum:SHA-256, SHA-512,如下图所示:

poi-bin-4.1.0-20190412.tar.gz文件为例,点击SHA-256和SHA-512的链接查看相关的值如下:

代码语言:javascript
复制
##SHA-256的值
d8db4f8228d87935ca46b0af72db68ad83f45b31d885e67b089d195b5ee800bb

##SHA-512的值
87499ab94882605ee2f407fc66e24c613ae98896b8d5f527b6cd8c604574922fc72d148da42962b2ee30ad18cd712e3de42bfe14770261b07217717c52a738a9

本文将简单介绍一下checksum(含义,作用)以及如何使用java程序计算出不同算法的checksum值,包括MD5、SHA-1,SHA-256以及SHA-512。

代码语言:javascript
复制
Checksum:总和检验码,校验和。
在数据处理和数据通信领域中,用于校验目的的一组数据项的和。
这些数据项可以是数字或在计算检验总和过程中看作数字的其它字符串。
通常是以十六进制为数制表示的形式。

【作用】就是用于检查文件完整性,检测文件是否被恶意篡改,比如文件传输(如插件、固件升级包等)场景使用。

接下来,我们一起看下怎么使用java程序产生相关的checksum值,本文以文件poi-bin-4.1.0-20190412.tar.gz为例,具体可以通过如下路径下载:

代码语言:javascript
复制
http://mirror.bit.edu.cn/apache/poi/release/bin/poi-bin-4.1.0-20190412.tar.gz

因为要使用不同算法的checksum值,包括MD5、SHA-1,SHA-256以及SHA-512,先定义一个枚举类,用于区分不同的算法。

代码语言:javascript
复制
package com.wangmengjun.tutorial.checksum;

public enum CheckSumAlgoType {

  MD5("MD5"), SHA_256("SHA-256"), SHA_512("SHA-512"), SHA_1("SHA1");
  

  private String name;

  private CheckSumAlgoType(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

}

接下来,我们就来看看几种计算文件checksum的方法:

  1. 使用java.security.MessageDigest
  2. 使用org.apache.commons.codec.digest.DigestUtils
  3. 使用com.google.common.io.Files.hash

一、使用java.security.MessageDigest

代码语言:javascript
复制
  public static String genChecksum1(File file, String checkSumAlgo) throws NoSuchAlgorithmException, IOException {
    MessageDigest messageDigest = MessageDigest.getInstance(checkSumAlgo);
    messageDigest.update(Files.readAllBytes(file.toPath()));
    byte[] digestBytes = messageDigest.digest();
    StringBuffer sb = new StringBuffer();
    for (byte b : digestBytes) {
      sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
    }
    return sb.toString();
  }

其中,下面的这段代码,

代码语言:javascript
复制
StringBuffer sb = new StringBuffer();
    for (byte b : digestBytes) {
      sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
    }
    return sb.toString();

可以使用javax.xml.bind.DatatypeConverter的方法来做,简化后的代码如下:

代码语言:javascript
复制
  public static String genChecksum1(File file, String checkSumAlgo) throws NoSuchAlgorithmException, IOException {
    MessageDigest messageDigest = MessageDigest.getInstance(checkSumAlgo);
    messageDigest.update(Files.readAllBytes(file.toPath()));
    byte[] digestBytes = messageDigest.digest();
    return DatatypeConverter.printHexBinary(digestBytes).toLowerCase();
  }

因为,DatatypeConverter.printHexBinary(digestBytes)返回的字符大写,

所以添加了toLowerCase()方法保持其一致性。

二、使用org.apache.commons.codec.digest.DigestUtils

使用commons-codec来完成,Maven工程需要添加依赖包,如:

代码语言:javascript
复制
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.13</version>
</dependency>

简单代码如下,通过调用类DigestUtils的静态方法完成指定checksum的计算即可:

代码语言:javascript
复制
  public static String genChecksum2(File file, CheckSumAlgoType checkSumAlgoType)
      throws FileNotFoundException, IOException {
    /**
     * 使用org.apache.commons.codec.digest.DigestUtils
     */
    String checksum = null;
    switch (checkSumAlgoType) {
    case MD5:
      checksum = DigestUtils.md5Hex(new FileInputStream(file));
      break;

    case SHA_1:
      checksum = DigestUtils.sha1Hex(new FileInputStream(file));
      break;

    case SHA_256:
      checksum = DigestUtils.sha256Hex(new FileInputStream(file));
      break;
    case SHA_512:
      checksum = DigestUtils.sha512Hex(new FileInputStream(file));
      break;
    default:
      checksum = DigestUtils.md5Hex(new FileInputStream(file));
    }

    return checksum;
  }

三、使用com.google.common.io.Files.hash

使用Guava来完成,Maven工程需要添加依赖包,如:

代码语言:javascript
复制
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>23.0</version>
</dependency>

简单代码如下,通过调用com.google.common.io.Files的hash方法即可:

代码语言:javascript
复制
  public static String genChecksum3(File file, CheckSumAlgoType checkSumAlgoType) throws IOException {
    /**
     * 使用Guava
     */
    String checksum = null;
    switch (checkSumAlgoType) {
    case MD5:
      checksum = com.google.common.io.Files.hash(file, Hashing.md5()).toString();
      break;
    case SHA_1:
      checksum = com.google.common.io.Files.hash(file, Hashing.sha1()).toString();
      break;

    case SHA_256:
      checksum = com.google.common.io.Files.hash(file, Hashing.sha256()).toString();
      break;
    case SHA_512:
      checksum = com.google.common.io.Files.hash(file, Hashing.sha512()).toString();
      break;
    default:
      checksum = com.google.common.io.Files.hash(file, Hashing.md5()).toString();
    }
    return checksum;
  }

验证

最后,我们一起来验证一下上述几种方法对文件的checksum计算。

代码语言:javascript
复制
  public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
    File file = new File("/users/wmj/Downloads/poi-bin-4.1.0-20190412.tar.gz");
    for (CheckSumAlgoType type : CheckSumAlgoType.values()) {
      System.out.println("采用" + type.getName() + "计算checksum");
      System.out.println(
          String.format("method=%s,checksum=%s", "genChecksum1", genChecksum1(file, type.getName())));
      System.out.println(String.format("method=%s,checksum=%s", "genChecksum2", genChecksum2(file, type)));
      System.out.println(String.format("method=%s,checksum=%s", "genChecksum3", genChecksum3(file, type)));
      System.out.println();
    }
  }

运行结果如下:

代码语言:javascript
复制
采用MD5计算checksum
method=genChecksum1,checksum=2fa39c79790c29c53368ec0c14fdea97
method=genChecksum2,checksum=2fa39c79790c29c53368ec0c14fdea97
method=genChecksum3,checksum=2fa39c79790c29c53368ec0c14fdea97

采用SHA-256计算checksum
method=genChecksum1,checksum=d8db4f8228d87935ca46b0af72db68ad83f45b31d885e67b089d195b5ee800bb
method=genChecksum2,checksum=d8db4f8228d87935ca46b0af72db68ad83f45b31d885e67b089d195b5ee800bb
method=genChecksum3,checksum=d8db4f8228d87935ca46b0af72db68ad83f45b31d885e67b089d195b5ee800bb

采用SHA-512计算checksum
method=genChecksum1,checksum=87499ab94882605ee2f407fc66e24c613ae98896b8d5f527b6cd8c604574922fc72d148da42962b2ee30ad18cd712e3de42bfe14770261b07217717c52a738a9
method=genChecksum2,checksum=87499ab94882605ee2f407fc66e24c613ae98896b8d5f527b6cd8c604574922fc72d148da42962b2ee30ad18cd712e3de42bfe14770261b07217717c52a738a9
method=genChecksum3,checksum=87499ab94882605ee2f407fc66e24c613ae98896b8d5f527b6cd8c604574922fc72d148da42962b2ee30ad18cd712e3de42bfe14770261b07217717c52a738a9

采用SHA1计算checksum
method=genChecksum1,checksum=f56e42474fa81676d82a38ae6a8df67194a50b93
method=genChecksum2,checksum=f56e42474fa81676d82a38ae6a8df67194a50b93
method=genChecksum3,checksum=f56e42474fa81676d82a38ae6a8df67194a50b93

我们可以看到,计算结果和Apache上显示的checksum是一致的。

本文主要给出了三种计算checksum的方式,包括:

  1. 使用java.security.MessageDigest
  2. 使用org.apache.commons.codec.digest.DigestUtils
  3. 使用com.google.common.io.Files.hash

当然,可能还有其它的实现方式和工具包,如果读者发现其它的也可以同步一下,一起学习。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二、使用org.apache.commons.codec.digest.DigestUtils
  • 三、使用com.google.common.io.Files.hash
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档