【问题标题】:C# SHA-256 vs. Java SHA-256. Different results?C# SHA-256 与 Java SHA-256。结果不一样?
【发布时间】:2018-08-03 22:05:46
【问题描述】:

我想将 Java 中的一些代码转换为 C#。

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 时,我得到了不同的哈希

更新:

例如:

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

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

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

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

【问题讨论】:

  • 如果使用"SHA-256",为什么方法命名为getMd5Hash
  • 我不太清楚。可能是这个方法在过去生成了MD5。我们只是将项目从 java 转换为 C#
  • 您如何解决此问题。你能在这里更新修复,我也面临同样的问题

标签: c# java .net cryptography sha256


【解决方案1】:

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

试试这个:

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

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

【讨论】:

    【解决方案2】:

    您链接到的 C# 代码也使用 salt - 但 Java 代码没有。如果您只使用一次 salt 而不是另一个,那么结果将会(并且应该!)不同。

    【讨论】:

    • 代码包括byte[] hash = digest.digest(SALT);。那不是用盐吗?
    【解决方案3】:
    hexString.append(Integer.toHexString(0xFF & hash[i]));
    

    您正在错误地构建哈希字符串。 Integer.toHexString 不包括前导零,所以虽然Integer.toHexString(0xFF) == "FF",但问题是Integer.toHexString(0x05) == "5"

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

    【讨论】:

      【解决方案4】:
      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 ; 
      
      }
      

      你可以使用下面的java来匹配C#的

      【讨论】:

        【解决方案5】:

        你并没有真正写下你是如何调用 SimpleHash 类的——使用哪些参数等等。

        但请注意,它的 ComputeHash 方法在其文档中有:

        哈希值格式化为 base64 编码的字符串。

        您的课程改为将输出格式化为十六进制,这显然会有所不同。

        此外,salt 在 SimpleHash 中被解释为 base64,而您的方法将其解释为 ASCII(或任何您的系统编码 - 很可能与 ASCII 兼容,并且字符串仅包含 ASCII 字符)。

        此外,SimpleHash 中的输出包括盐(允许在使用随机盐时为“验证”部分复制它),而您的方法中没有。

        (其他答案已经提到了更多点。)

        【讨论】:

          猜你喜欢
          • 2014-08-19
          • 2016-03-29
          • 2016-08-03
          • 1970-01-01
          • 2021-04-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-09
          相关资源
          最近更新 更多