【问题标题】:SHA256Digest is returning a weird hashSHA256Digest 返回一个奇怪的哈希
【发布时间】:2012-04-11 21:20:02
【问题描述】:

BlackBerry 应用程序中,我使用此代码从密码中获取哈希:

        SHA256Digest sha256d = new SHA256Digest();
        byte[] passwordData = null;

        try {
            passwordData = password.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        DigestOutputStream outputStream = new DigestOutputStream(sha256d, null);
        try {
            outputStream.write(passwordData);
        } catch (IOException e) {
            e.printStackTrace();
        }

        byte[] hashedValue = sha256d.getDigest();
        tempSHA256Password = new String(hashedValue);
        System.out.println(tempSHA256Password);

在此代码块的末尾,tempSHA256Password 将如下所示:ëÇ#ÎiGê8óq =ßÝ÷<rê¨_FR»ã ... 所以绝不是我所期待的。我期待一个看起来像这样的字符串:ebc723ce6947ea38f371a03d0cdfddf73c840f7215eaa85f031446529bbb16e3

我做错了什么?

【问题讨论】:

    标签: java blackberry sha256


    【解决方案1】:

    安装于tempSHA256Password = new String(hashedValue); 试试这个代码:

    StringBuffer buffer = new StringBuffer();
    for(byte b : hashedValue)
    {
        buffer.append(String.format("%02x",b<0 ? b+256 : b));
    }
    tempSHA256Password = buffer.toString();
    

    【讨论】:

    • 你能解释一下你为什么使用b&lt;0 ? b+256 : b吗?为什么/如何b 小于 0?为什么要加上 256 呢?除此之外,谢谢!此解决方案有效。
    • Java 中的字节总是有符号的,但在散列值中,字节 0xff 意味着 255,而不是 -1。当(隐式)将字节转换为 int 时,此代码将字节值解释为无符号。
    • 实际上,这段代码似乎遗漏了几个 0(零)。例如,取字符串tobehashed。实际的结束十六进制值应该是a4ed677da365940d77fff663b7c5e27d9e166514c681df2fa2024089e0bfc422,但此代码返回a4ed677da36594d77fff663b7c5e27d9e166514c681df2fa224089e0bfc422,省略了几个零
    • 如果我没记错格式字符串,可以使用buffer.append(String.format("%02x",b&lt;0 ? b+256 : b)); 轻松解决此问题。
    • 好的,谢谢你的提示。那应该可以……但是,在黑莓上不行,因为黑莓没有 String.format 方法。我想我必须想办法用 MessageFormat.format 做到这一点......
    【解决方案2】:

    这就是问题所在:

    tempSHA256Password = new String(hashedValue);
    

    它试图从任意二进制数据创建一个字符串,就好像它是使用平台默认编码的文本编码一样。听起来您正在寻找十六进制。 Java 中有大量不同的十六进制编码实用程序库 - 例如,您可能想查看 Apache Commons Codec

    【讨论】:

    • 确实,我正在寻找十六进制字符串。但是,我无法将 Apache 库导入 BlackBerry 项目。好像我只能在 BB 上使用 j2me 库。
    【解决方案3】:

    不能直接打印二进制值:

    tempSHA256Password = new String(hashedValue);
    System.out.println(tempSHA256Password);
    

    所以如果你想把它转换成十六进制你可以使用这个方法:

    static final String HEXES = "0123456789ABCDEF";
    public static String getHex( byte [] raw ) {
      if ( raw == null ) {
        return null;
      }
      final StringBuffer hex = new StringBuffer( 2 * raw.length );
      for ( final byte b : raw ) {
        hex.append(HEXES.charAt((b & 0xF0) >> 4))
         .append(HEXES.charAt((b & 0x0F)));
      }
      return hex.toString();
    }
    

    此方法来自here,如果有兴趣,您还有其他示例。

    【讨论】:

    • 我最终使用了this。它与您的解决方案类似。
    • 确实是一回事,顺便说一句,您的链接提供了更多的 cmets,谢谢!
    • 如果您确实想让您的答案适合 BlackBerry OS,您应该将 StringBuilder 替换为 StringBuffer btw。此外,您可以删除 Base64 编码部分,这不是我想要做的。
    【解决方案4】:

    你看到的是二进制形式的哈希。您必须将其转换为十六进制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-20
      • 2017-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多