【问题标题】:Java's MessageDigest SHA1-algorithm returns different result than SHA1-function of phpJava 的 MessageDigest SHA1 算法返回的结果与 php 的 SHA1 函数不同
【发布时间】:2011-11-28 03:30:15
【问题描述】:

我有一个包含用户名和密码的 SQL 表。密码使用 MessageDigest 的 digest() 方法进行编码。如果我使用 MessageDigest 的 digest() 方法对密码进行编码 - 比如说“abcdef12”,然后将其转换为十六进制值,则字符串与使用 PHP 的 SHA1 方法进行相同操作时不同。不过,我希望这些值完全相同。

用于对密码进行编码的代码:

MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] passbyte;
passbyte = "abcdef12".getBytes("UTF-8");
passbyte = md.digest(passbyte);

字符串到十六进制的转换是使用这种方法完成的:

public static String convertStringToHex(String str) {

    char[] chars = str.toCharArray();

    StringBuffer hex = new StringBuffer();
    for (int i = 0; i < chars.length; i++) {
        hex.append(Integer.toHexString((int) chars[i]));
    }

    return hex.toString();
}

密码:abcdef12

这是许多 SHA1-hash 在线生成器和 PHP SHA1()-function 返回的密码:d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef

这是 MessageDigest 编码的密码:d253e3bd69ce1e7ce674345fd5faa1a3c2e2030ef

我是不是忘记了什么?

伊戈尔。

编辑:我发现有人遇到类似问题:C# SHA-1 vs. PHP SHA-1...Different Results?。解决方案是更改编码。但我无法更改服务器端的编码,因为该 SQL 表中的密码不是由我的应用程序创建的。 我使用 JavaScript SHA1 类(更准确地说:Google Web Toolkit 类)使用客户端 SHA1 编码。它按预期工作和编码字符串,但显然使用 ASCII 字符?..

【问题讨论】:

    标签: java php sha1


    【解决方案1】:

    或者试试这个:

    MessageDigest md = MessageDigest.getInstance("SHA-1");
    md.update(clearPassword.getBytes("UTF-8"));
    return new BigInteger(1 ,md.digest()).toString(16));
    

    罗伊干杯

    【讨论】:

    • 对于初学者来说,BigInteger 不输出前导零,也就是说,07 变成了 7。
    【解决方案2】:

    它与编码无关。输出将完全不同。

    首先,您的函数 convertStringToHex() 不输出前导零,也就是说,07 变成了 7

    其余的(将89 更改为2030)也可能与该功能有关。尝试在passbyte = md.digest(passbyte); 之后查看passbyte 的值。

    【讨论】:

    • 谢谢!你的回答解决了我的问题。我未能正确地将字节数组转换为十六进制字符串!我使用了@stivlo 的方法,效果很好!我打算将此响应标记为正确,但在这种情况下,我希望我可以将两个给定的响应都标记为正确的!谢谢你们!
    【解决方案3】:

    试试这个 - 它对我有用:

    MessageDigest md = MessageDigest.getInstance(algorithm);
    md.update(original.getBytes());
    byte[] digest = md.digest();
    StringBuffer sb = new StringBuffer();
    for (byte b : digest) {
        sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
    }
    return sb.toString();
    

    问候, 康基

    【讨论】:

      【解决方案4】:

      我的 Java SHA-1 哈希函数与 PHP 具有相同的摘要:

      public static String computeSha1OfString(final String message) 
          throws UnsupportedOperationException, NullPointerException {
              try {
                     return computeSha1OfByteArray(message.getBytes(("UTF-8")));
              } catch (UnsupportedEncodingException ex) {
                      throw new UnsupportedOperationException(ex);
              }
      }
      
      private static String computeSha1OfByteArray(final byte[] message)
          throws UnsupportedOperationException {
              try {
                  MessageDigest md = MessageDigest.getInstance("SHA-1");
                  md.update(message);
                  byte[] res = md.digest();
                  return toHexString(res);
              } catch (NoSuchAlgorithmException ex) {
                  throw new UnsupportedOperationException(ex);
              }
      }
      

      我已添加到我的单元测试中:

      String sha1Hash = StringHelper.computeSha1OfString("abcdef12");
      assertEquals("d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef", sha1Hash);
      

      该类的完整源代码是on github

      【讨论】:

      • 确实 - 您的代码生成正确的 SHA1(或者更确切地说:与 php 的 SHA1 相同)。但是,我正在编写一个必须登录到现有数据库的应用程序。该数据库不是我自己创建的(密码加密也不是)。但是 它使用我的示例中编写的 MessageDigest 并因此在该字符串上运行 Base64.decode 会返回不同的结果(在我的示例中指定的结果)而不是您的正确结果,我也使用该结果JavaScript SHA1 类。有什么方法可以比较它们吗?我不知道 MessageDigest 是如何返回其他结果的。
      猜你喜欢
      • 2012-10-12
      • 2017-05-01
      • 2021-06-06
      • 2013-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-30
      相关资源
      最近更新 更多