Java SHA将相同的字符串散列到不同的blob中

Java SHA将相同的字符串散列到不同的blob中,java,passwords,sha,Java,Passwords,Sha,我使用以下代码对传入字符串进行散列,希望多次应用于该方法的相同内容将始终得到相同的结果。该场景将用于密码哈希和稍后的验证。但它似乎不起作用-我为同一个输入字符串得到了两个不同的blob。我的代码是否有任何错误或遗漏 public synchronized String encrypt(String token) { try { MessageDigest sha = MessageDigest.getInstance("SHA"); sha.reset()

我使用以下代码对传入字符串进行散列,希望多次应用于该方法的相同内容将始终得到相同的结果。该场景将用于密码哈希和稍后的验证。但它似乎不起作用-我为同一个输入字符串得到了两个不同的blob。我的代码是否有任何错误或遗漏

public synchronized String encrypt(String token) {
    try {
        MessageDigest sha = MessageDigest.getInstance("SHA");
        sha.reset();
        sha.update(token.getBytes("UTF-8"));
        byte[] raw = sha.digest();
        System.out.println("raw = " + raw.toString());
        String hash = Base64.encodeBase64(raw).toString();
        return hash;
    } catch (Exception e) {
    }

    return token;
}

你真的没有提供足够的信息,但我怀疑你被这件事分散了注意力:

System.out.println("raw = " + raw.toString());
这将打印出类似
[B@30a4effe
它与字节数组中的数据无关。您应该打印出
哈希值
——如果您的
令牌
确实相同,则所有调用的哈希值都应该相同

(正如Dan所指出的,您的方法的名称不恰当:哈希不是加密。此外,请不要捕获
异常
,或者像这样吞下异常。在失败时只返回
令牌
,这似乎很奇怪。)


编辑:如前所述,我假设
Base64.encode
实际上返回一个字符串,但它可能不返回。我建议使用公共域和合理的API-编码调用返回一个字符串,这是完全合适的。当然,您不需要显式的
toString()
也调用…

我不知道您使用的是什么Base64类,但我假设使用的是Apache Commons中的一个。您正在这样做:

String hash = Base64.encodeBase64(raw).toString();
它正在对从
Base64.encodeBase64()
方法返回的任意随机字节数组调用
toString
方法。这就是为什么每次结果都是随机的,您只是将对象引用作为字符串返回。请改为尝试以下操作:

String hash = Base64.encodeBase64String(raw);
编辑


正如在另一篇文章中指出的,直接转换为字符串可能是一个坏主意。我稍微编辑了我的答案以反映这一点。

添加相关语言的标记。我相信您忘记添加
Java
。感谢捕获!真正的加密需要哪些额外的步骤?我的代码就是这样编写的告诉我密码加密的示例代码。@tom:对于密码,你可能不应该使用可逆加密。即使散列本身也不好——你至少应该对散列进行加密,并选择合适的散列算法。(有关详细信息,请搜索salt散列加密。)非常感谢您的解释。但这实际上并不能解决他的问题。他正在对字节数组调用
toString
,并将其作为最终结果返回。这就是为什么每次结果都是随机的。@Perception:这取决于
Base64返回的内容。encodeBase64(原始)
返回的内容-有很多Base64类。