简体   繁体   English

C# SHA-256 与 Java SHA-256。 结果不一样?

[英]C# SHA-256 vs. Java SHA-256. Different results?

I want to convert a some code which is in Java to C#.我想将 Java 中的一些代码转换为 C#。

Java Code: 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!");
  }

When I tried to use the SimpleHash class I got different hashs当我尝试使用SimpleHash class 时,我得到了不同的哈希值

UPDATE:更新:

For example:例如:

Java: byte[] hash = digest.digest(SALT); Java: 字节[] hash = digest.digest(SALT); generates (first 6 bytes):生成(前 6 个字节):

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

C# code (class SimpleHash): string hashValue = Convert.ToBase64String(hashWithSaltBytes); C# 代码(SimpleHash 类):字符串 hashValue = Convert.ToBase64String(hashWithSaltBytes); hashWithSaltBytes has (first 6 bytes): hashWithSaltBytes 有(前 6 个字节):

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

The String.getBytes method encodes the string to bytes using the platform's default charset, whereas the example code you linked uses UTF-8. String.getBytes 方法使用平台的默认字符集将字符串编码为字节,而您链接的示例代码使用 UTF-8。

Try this:尝试这个:

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

Secondly, the Integer.toHexString method returns the hexadecimal result with no leading 0s.其次, Integer.toHexString 方法返回没有前导 0 的十六进制结果。

The C# code you link to also uses salt - but the Java code does not.您链接到的 C# 代码也使用盐 - 但 Java 代码不使用。 If you use salt with once, but not the other, then the results will be (and should be.) different.如果您一次使用盐,而不是另一个,那么结果将(并且应该是)不同。

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

You are building the hash string incorrectly.您正在错误地构建 hash 字符串。 Integer.toHexString does not include leading zeros, so while Integer.toHexString(0xFF) == "FF" , the problem is that Integer.toHexString(0x05) == "5" . Integer.toHexString不包括前导零,因此虽然Integer.toHexString(0xFF) == "FF" ,但问题是Integer.toHexString(0x05) == "5"

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

public static String getEncryptedPassword(String clearTextPassword) throws NoSuchAlgorithmException{

    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(clearTextPassword.getBytes(StandardCharsets.UTF_8));
    byte[] digest = md.digest();
    String hex = String.format("%064x", new BigInteger(1, digest));
    String st = new String(hex.toUpperCase());
    for (int i = 2; i < (hex.length() + hex.length() / 2) - 1 ;) {
        st = new StringBuffer(st).insert(i, "-").toString();
            i = i + 3;        
    }
    return st ; 

}

You can use the following java to match that of C#您可以使用以下 java 来匹配 C#

You didn't really write how you called the SimpleHash class - with which parameters and such.您并没有真正写下您如何调用 SimpleHash class - 使用哪些参数等。

But note that its ComputeHash method has in its documentation:但请注意,其ComputeHash方法在其文档中有:

Hash value formatted as a base64-encoded string. Hash 值格式化为 base64 编码的字符串。

Your class instead formats the output in hexadecimal, which will obviously be different.您的 class 改为将 output 格式化为十六进制,这显然会有所不同。

Also, the salt is in SimpleHash interpreted as base64, while your method interprets it as ASCII (or whatever your system encoding is - most probably something ASCII-compatible, and the string only contains ASCII characters).此外,盐在 SimpleHash 中被解释为 base64,而您的方法将其解释为 ASCII(或任何您的系统编码 - 很可能与 ASCII 兼容,并且字符串仅包含 ASCII 字符)。

Also, the output in SimpleHash includes the salt (to allow reproducing it for the "verify" part when using random salt), which it doesn't in your method.此外,SimpleHash 中的 output 包括盐(以允许在使用随机盐时为“验证”部分复制它),它不在您的方法中。

(More points are already mentioned by the other answers.) (其他答案已经提到了更多要点。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM