MessageDigest在不同的计算机上散列不同

我遇到MessageDigest在不同计算机上返回不同哈希值的问题。

一台计算机在Windows Vista上运行32位Java,另一台在Mac OS上运行64位Java。 我不确定是不是因为MessageDigest是依赖于机器的,或者我需要在某处明确指定字符编码,或者可能是其他东西。 这是代码:

public static boolean authenticate(String salt, String encryptedPassword, char[] plainTextPassword ) throws NoSuchAlgorithmException { // do I need to explcitly specify character encoding here? --> String saltPlusPlainTextPassword = salt + new String(plainTextPassword); MessageDigest sha = MessageDigest.getInstance("SHA-512"); // is this machine dependent? --> sha.update(saltPlusPlainTextPassword.getBytes()); byte[] hashedByteArray = sha.digest(); // or... perhaps theres a translation problem here? --> String hashed = new String(hashedByteArray); return hashed.equals(encryptedPassword); } 

这些代码应该在这两台不同的机器上执 如果它与我编写它的方式是机器相关的,还有另一种方法来散列这些更便携的密码吗? 谢谢!

编辑:::::

这是我用来生成盐的代码:

 public static String getSalt() { int size = 16; byte[] bytes = new byte[size]; new Random().nextBytes(bytes); return org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(bytes); } 

解:::

感谢已接受的解决方案,我能够修复我的代码:

 public static boolean authenticate_(String salt, String encryptedPassword, char[] plainTextPassword ) throws NoSuchAlgorithmException, UnsupportedEncodingException { // This was ok String saltPlusPlainTextPassword = salt + new String(plainTextPassword); MessageDigest sha = MessageDigest.getInstance("SHA-512"); // must specify "UTF-8" encoding sha.update(saltPlusPlainTextPassword.getBytes("UTF-8")); byte[] hashedByteArray = sha.digest(); // Use Base64 encoding here --> String hashed = org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(hashedByteArray); return hashed.equals(encryptedPassword); } 

编码会给你带来麻烦。 首先在这里:

 saltPlusPlainTextPassword.getBytes() 

这将使用机器默认编码 。 馊主意。 指定“UTF-8”作为简单的解决方案。 (它保证会存在。)

接下来会导致问题:

 String hashed = new String(hashedByteArray); 

hashedByteArray是任意二进制数据。 要将其安全地转换为文本,请使用base-64编码或仅使用hex。 同样,您当前正在使用默认编码,该编码因机器而异。 在Java中有大量用于base64编码的第三方库。

可能Jon Skeet上面的解决方案是原因,他的建议应该被考虑在内,但另一个可能的原因是对盐的误解。

Salt是一个半秘密随机值,在散列之前应用于String。 这使得在尝试猜测原始字符串是什么时执行暴力攻击更加困难,因为攻击者可能不知道盐。

盐值通常因安装而异。 实际原因可能只是您在不同的机器上设置了不同的盐值。