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

如何多次哈希并每轮拼接字符串?SHA-256实现疑问

问题解析与解决方案

嘿,我来帮你把这个问题掰明白~

首先先解释你困惑的Code 1 和 Code 2 结果不同的原因:
两者的核心差异在于第二次哈希的输入完全不一样:

  • Code 1 是直接对「第一次哈希得到的字节数组」做第二次哈希,全程没有经过字符串的编码和解码,相当于计算 SHA256(SHA256(原始字节数组))。
  • Code 2 则是把第一次哈希的字节数组转成十六进制字符串,再把这个字符串转回字节数组,然后对这个字符串的字节做第二次哈希。因为十六进制字符串的字节和原始哈希字节完全不是一回事(比如哈希字节里的0x0A转成十六进制是"0a",对应的字节是0x30和0x61),所以两次哈希的输入天差地别,结果自然不同。

接下来是你的核心问题:每次将哈希(Byte[])解码为十六进制字符串以拼接R,再重新编码为字节的正确方式

按照你的伪逻辑(每次把上一次的哈希十六进制结果拼R,再哈希),正确的步骤和代码应该是这样的:

正确实现思路

  1. 初始输入:密码字符串直接拼接R,转成UTF-8字节数组。
  2. 循环100次:
    • 对当前输入的字节数组计算SHA-256哈希,得到字节数组。
    • 将哈希字节数组转换成固定64位的小写(或大写)十六进制字符串(必须补前导零,保证长度一致)。
    • 输出这个十六进制哈希值。
    • 把这个十六进制字符串和R拼接,转成UTF-8字节数组,作为下一次哈希的输入。

修正后的示例代码

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class RepeatedHash {
    public static void main(String[] args) throws NoSuchAlgorithmException {
        String password = "password";
        String R = "f@ghj!$g";
        int totalIterations = 100;

        // 初始化第一次输入:密码拼接R
        String currentInput = password.concat(R);
        byte[] inputBytes = currentInput.getBytes(StandardCharsets.UTF_8);

        for (int i = 0; i < totalIterations; i++) {
            // 每次计算哈希都创建新的MessageDigest实例(也可以复用并调用reset())
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = md.digest(inputBytes);
            
            // 转成64位小写十六进制字符串,补前导零避免长度缺失
            String hexHash = String.format("%064x", new BigInteger(1, hashBytes));
            System.out.println(hexHash); // 输出当前哈希值
            
            // 拼接R,准备下一轮输入
            currentInput = hexHash.concat(R);
            inputBytes = currentInput.getBytes(StandardCharsets.UTF_8);
        }
    }
}

关键注意事项

  • 固定十六进制字符串长度:必须用%064x格式化,因为SHA-256是256位,对应32字节、64个十六进制字符。如果省略前导零(比如用%x),会导致字符串长度不足64,拼接R后的输入长度不一致,最终哈希结果完全错误。
  • 统一大小写:要么全小写(%064x)要么全大写(%064X),不能混合。因为A和a的UTF-8字节值不同,会导致拼接后的输入字节数组不一样,哈希结果也会不同。
  • 正确使用MessageDigest:每次计算新的哈希时,要么新建实例,要么调用md.reset()清空之前的状态,避免残留的update数据干扰结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:47:23