2011-08-17 148 views
1

我想将一些在Java中的代码转换为C#。C#SHA-256与Java SHA-256。不同的结果?

Java代码:

private static final byte[] SALT = "NJui8*&N823bVvy03^4N".getBytes(); 

    public static final String getSHA256Hash(String secret) 
    { 
    try { 
     MessageDigest digest = MessageDigest.getInstance("SHA-256"); 
     digest.update(secret.getBytes()); 
     byte[] hash = digest.digest(SALT); 
     StringBuffer hexString = new StringBuffer(); 
     for (int i = 0; i < hash.length; i++) { 
     hexString.append(Integer.toHexString(0xFF & hash[i])); 
     } 
     return hexString.toString(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 
    throw new RuntimeException("SHA-256 realization algorithm not found in JDK!"); 
    } 

当我试图使用the SimpleHash class我得到不同hashs

UPDATE:

例如:

爪哇:字节[]散列= digest.digest(SALT); 生成(前6个字节):

[0] = 9 
[1] = -95 
[2] = -68 
[3] = 64 
[4] = -11 
[5] = 53 
.... 

C#代码(类SimpleHash): 串散列值= Convert.ToBase64String(hashWithSaltBytes); hashWithSaltBytes具有(前6个字节):

[0] 175 byte 
[1] 209 byte 
[2] 120 byte 
[3] 74 byte 
[4] 74 byte 
[5] 227 byte 
+3

为什么法名为'getMd5Hash'如果你使用'“SHA-256”'? – dtb

+0

我不知道。可能是这种方法在过去生成MD5。我们只是将项目从java转换为C# –

回答

6

String.getBytes method编码串使用平台的默认字符集字节,而你链接的示例代码使用UTF-8。

试试这个:

digest.update(secret.getBytes("UTF-8")); 

其次,Integer.toHexString method返回十六进制的结果,没有前导零。

+0

谢谢。解决了这个问题。 –

2

您链接到的C#代码也使用salt - 但Java代码没有。如果一次使用盐,但不使用其他盐,那么结果将会不同(和应该是!)。

+0

该代码包含'byte [] hash = digest.digest(SALT);'。那不是使用盐吗? – dtb

+0

啊,我以前没有发现... – Cocowalla

2
hexString.append(Integer.toHexString(0xFF & hash[i])); 

您错误地建立散列字符串。 Integer.toHexString不包含前导零,所以虽然Integer.toHexString(0xFF) == "FF",问题是Integer.toHexString(0x05) == "5"

建议修正:String.format("%02x", hash[i] & 0xFF)

0

你真的不写你怎么叫SimpleHash类 - 有哪些参数和这样的。

但请注意,其ComputeHash方法都有其文档中:格式化为base64编码字符串

哈希值。

你的类改为以十六进制格式化输出,这显然是不同的。当你的方法将它解释为ASCII(或者任何你的系统编码 - 很可能是与ASCII兼容的东西,并且字符串只包含ASCII字符)时,SimpleHash将salt解释为base64。

此外,SimpleHash中的输出包括salt(允许在使用随机盐时对其进行“验证”部分的重现),而不是在您的方法中。

(详细点已经由其他的答案中提到。)