You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 8与OpenJDK 17的HMAC哈希值差异问题及解决方案

文件HMAC哈希跨Java版本一致性问题解决

我在实现通过对比文件HMAC哈希值验证文件完整性的功能时发现:Java 8(IBM J9 VM)与OpenJDK 17环境下,文本文件的哈希值一致,但xlsx这类非文本文件的哈希值存在差异。以下是问题代码、修正后的可行代码及不同版本的输出结果:

问题代码

import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.SystemUtils;

@Slf4j
public class TestHashing {

  private static String HMACH_KEY = "some_key";

  private static String generateHMACHash(String message) {
    if (message == null) {
      message = "";
    }

    Mac sha256HMAC = null;
    try {
      sha256HMAC = Mac.getInstance("HmacSHA256");
      SecretKeySpec secretKeySpec = new SecretKeySpec(HMACH_KEY.getBytes(), "HmacSHA256");
      sha256HMAC.init(secretKeySpec);
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
      log.debug("Getting Exception in Hashing ", e.getMessage());
      e.printStackTrace();
    }

    return Base64.encodeBase64String(sha256HMAC.doFinal(message.toUpperCase().getBytes()));
  }

  public static void main(String[] args) throws IOException {

    String version = SystemUtils.JAVA_SPECIFICATION_VERSION;

    System.out.println("Java Virtual Machine specification version  : " + System.getProperty("java.vm.specification.version"));
    System.out.println("Java Virtual Machine specification vendor : " + System.getProperty("java.vm.specification.vendor"));
    System.out.println("Java Virtual Machine specification name : " + System.getProperty("java.vm.specification.name"));
    System.out.println("Java Virtual Machine implementation version : " + System.getProperty("java.vm.version"));
    System.out.println("Java Virtual Machine implementation vendor : " + System.getProperty("java.vm.vendor"));
    System.out.println("Java Virtual Machine implementation name : " + System.getProperty("java.vm.name"));

    String fileName = "C:\\test\\fileTest.txt";
    File file = new File(fileName);
    String data = FileUtils.readFileToString(file, "UTF-8");
    String output = generateHMACHash(data);
    System.out.println(fileName + " FILE USING JAVA VERSION" + version);
    System.out.println(output);

    fileName = "C:\\test\\fileTest.xlsx";
    file = new File(fileName);
    data = FileUtils.readFileToString(file, "UTF-8");
    output = generateHMACHash(data);
    System.out.println(fileName + " FILE USING JAVA VERSION" + version);
    System.out.println(output);
  }

}

修正后的可行代码

private static String generateHMACHash(File file) throws Exception {

    Mac sha256HMAC = Mac.getInstance("HmacSHA256");
    SecretKeySpec secretKeySpec = new SecretKeySpec(HMACH_KEY.getBytes(), "HmacSHA256");
    sha256HMAC.init(secretKeySpec);

    // 获取文件输入流读取文件内容
    FileInputStream fis = new FileInputStream(file);

    // 创建字节数组以分块读取数据
    byte[] byteArray = new byte[1024];
    int bytesCount = 0;

    // 读取文件数据并更新消息摘要
    while ((bytesCount = fis.read(byteArray)) != -1) {
      sha256HMAC.update(byteArray, 0, bytesCount);
    }

    // 关闭输入流
    fis.close();

    // 存储doFinal()方法返回的字节
    byte[] bytes = sha256HMAC.doFinal();

    // 将字节数组转换为十六进制字符串
    StringBuilder sb = new StringBuilder();

    // 遍历字节数组
    for (int i = 0; i < bytes.length; i++) {

      // 将十进制字节转换为十六进制并追加到StringBuilder
      sb.append(Integer
          .toString((bytes[i] & 0xff) + 0x100, 16)
          .substring(1));
    }

    // 返回完整哈希值
    return sb.toString();
  }

不同Java版本输出结果

OpenJDK 17输出

Java虚拟机规范版本: 17
Java虚拟机规范厂商: Oracle Corporation
Java虚拟机规范名称: Java Virtual Machine Specification
Java虚拟机实现版本: 17.0.7+7
Java虚拟机实现厂商: Eclipse Adoptium
Java虚拟机实现名称: OpenJDK 64-Bit Server VM
C:\test\fileTest.txt 文件使用Java版本17
VfhDrMk6e8t2bdKM0r+AeCfBA+iYNAKmBDhkvocMcpU=
C:\test\fileTest.xlsx 文件使用Java版本17
vPR0xPL0dIQgrYpSN/JJELMjFm90JoM0LqAeKL+2Yfo=

Java 8(IBM J9 VM)输出

Java虚拟机规范版本: 1.8
Java虚拟机规范厂商: Oracle Corporation
Java虚拟机规范名称: Java Virtual Machine Specification
Java虚拟机实现版本: 2.9
Java虚拟机实现厂商: IBM Corporation
Java虚拟机实现名称: IBM J9 VM
C:\test\fileTest.txt 文件使用Java版本1.8
VfhDrMk6e8t2bdKM0r+AeCfBA+iYNAKmBDhkvocMcpU=
C:\test\fileTest.xlsx 文件使用Java版本1.8
n5Fb6b34VOnRUsGzYGcQn7vTAPNcLfg1zFoXJ2ZvM/w=

内容的提问来源于stack exchange,提问作者kvk95

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 19:30:04