字符串SHA-512编码:C#和JAVA结果不同

我试图比较sha512编码的两个不同的字符串。 但是,结果是不同的。 它可能是我所说的编码问题。 我希望你能帮助我。

这是我的Java代码:

MessageDigest digest = java.security.MessageDigest.getInstance("SHA-512"); digest.update(MyString.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); for (int i = 0; i < messageDigest.length; i++) { String h = Integer.toHexString(0xFF & messageDigest[i]); while (h.length() < 2) h = "0" + h; hexString.append(h); } return hexString.toString(); 

而且,这是我的C#代码:

  UnicodeEncoding UE = new UnicodeEncoding(); byte[] hashValue; byte[] message = UE.GetBytes(MyString); SHA512Managed hashString = new SHA512Managed(); string hex = ""; hashValue = hashString.ComputeHash(message); foreach (byte x in hashValue) { hex += String.Format("{0:x2}", x); } return hex; 

问题出在哪儿 ? 很多人

UPDATE

如果我没有指定编码类型,我认为它假设为Unicode。 结果是这个(没有指定任何东西):

 Java SHA: a99951079450e0bf3cf790872336b3269da580b62143af9cfa27aef42c44ea09faa83e1fbddfd1135e364ae62eb373c53ee4e89c69b54a7d4d268cc2274493a8 C# SHA: 70e6eb559cbb062b0c865c345b5f6dbd7ae9c2d39169571b6908d7df04642544c0c4e6e896e6c750f9f135ad05280ed92b9ba349de12526a28e7642721a446aa 

相反,如果我在Java中指定UTF-16:

 Java UTF-16: SHA f7a587d55916763551e9fcaafd24d0995066371c41499fcb04614325cd9d829d1246c89af44b98034b88436c8acbd82cd13ebb366d4ab81b4942b720f02b0d9b 

它总是不同的!

您使用的C#中的UnicodeEncoding对应于little-endian UTF-16编码,而Java中的“UTF-16”对应于big-endian UTF-16编码。 另一个区别是,如果您不要求C#,则不会输出字节顺序标记(在API中称为“前导码”),而Java中的“UTF-16”始终会生成它。 要使两个程序兼容,您可以使Java也使用little-endian UTF-16:

 digest.update(MyString.getBytes("UTF-16LE")); 

或者您可以切换到其他一些众所周知的编码,如UTF-8。

这里,

 digest.update(MyString.getBytes()); 

您应该在String#getBytes()方法中明确指定所需的字符编码。 否则它将默认为Charset#defaultCharset()获得的平台默认字符集。

相应修复:

 digest.update(MyString.getBytes("UTF-16LE")); 

至少应该与UnicodeEncoding在内部使用的字符集相同。


具体问题无关 ,Java还有一个增强的for循环和一个String#format()

原因可能是你没有指定在将字符串转换为字节时使用的编码,java使用平台默认编码,而UnicodeEncoding似乎使用utf-16。

编辑:

UnicodeEncoding的文档说

此构造函数创建一个使用小端字节顺序的实例,提供Unicode 字节顺序标记 ,并且在检测到无效编码时不会引发exception。

然而,Javas“utf-16”似乎默认为大端字节顺序。 使用字符编码最好是特定的,有一个UnicodeEncoding构造函数采用两个布尔指定的字节顺序,而在java中还有“utf-16le”和“utf-16be”。 您可以在c#中尝试以下操作

 new UnicodeEncoding(true, false) // big endian, no byte order mark 

在java中

 myyString.getBytes("utf-16be") 

或者甚至更好地在两种情况下都使用“utf-8” / Encoding.UTF8 ,因为它不受不同的byteorder的影响