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

为何SHA-256消息摘要在Java与j2objc环境下结果不一致?

问题分析与解决

这不是你的操作失误,而是j2objc的jre_emul库中MessageDigest的实现和原生Java SE在digest(byte[] buf, int offset, int len)方法的行为上存在差异导致的。

先拆解原生Java代码的执行逻辑

你的代码在原生Java 8中的行为完全符合规范:

  1. 创建SHA-256的MessageDigest实例,更新64个空字节;
  2. 调用md.digest():计算64个空字节的SHA-256哈希,返回结果存入tmp,同时重置MessageDigest实例的状态;
  3. 调用md.digest(tmp, 0, tmp.length):此时md已经被重置,没有任何待计算的输入数据,因此会计算空输入的SHA-256哈希,并将结果写入tmp数组中;
  4. 最终输出的是空输入SHA-256的Base64编码,也就是你看到的47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=,这个值是标准的空输入SHA-256哈希结果。

j2objc输出不同的原因

j2objc的jre_emul库对MessageDigest.digest(byte[] buf, int offset, int len)的实现没有严格遵循Java规范:

  • 它可能错误地将传入的tmp数组当作输入数据而非输出缓冲区,也就是调用这个方法时,实际计算的是tmp数组(即64个空字节的SHA-256结果)的哈希值,而非空输入的哈希;
  • 也有可能是md.digest()方法没有正确重置MessageDigest的状态,导致后续调用digest(buf, offset, len)时,继续基于之前的64个空字节状态计算,再叠加tmp的数据,最终得到不同的结果。

兼容Java和j2objc的修正方案

避免使用行为不一致的digest(byte[] buf, int offset, int len)方法,改用更明确、兼容的写法来实现你的需求:

import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class TestScrypt {
    public static void main(String[] args) throws NoSuchAlgorithmException, DigestException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(new byte[64]);
        byte[] tmp = md.digest();
        
        // 改用明确的重置+计算+复制逻辑,替代digest(buf, offset, len)
        md.reset();
        byte[] emptyHash = md.digest();
        System.arraycopy(emptyHash, 0, tmp, 0, emptyHash.length);
        
        System.out.println("Result:" + Base64.getEncoder().encodeToString(tmp));
    }
}

这个写法在原生Java和j2objc编译后都会输出相同的结果,因为它完全规避了有行为差异的方法,用更直观的步骤实现了覆盖tmp数组的逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:45:38