【问题标题】:SHA-256 same string return different byte[]?SHA-256 相同的字符串返回不同的字节 []?
【发布时间】:2016-01-08 17:07:00
【问题描述】:

我需要 SHA-256 作为 AES-256 的密钥。 但我的示例 SHA-256 是:

MessageDigest messageDigest;
messageDigest = MessageDigest.getInstance("SHA-256");

String input = new String("ALIBABA");
messageDigest.update(input.getBytes(Charset.forName("UTF-8")));
byte[] hash = messageDigest.digest();
String hash1s = new String(hash,StandardCharsets.UTF_8);
System.out.println("HASH 1 is "+hash1s);
System.out.println("HASH 1 is "+hash);

String input2 = new String("ALIBABA");
messageDigest.update(input2.getBytes(Charset.forName("UTF-8")));
byte[] hash2 = messageDigest.digest();
String hash2s = new String(hash2,StandardCharsets.UTF_8);
System.out.println("HASH 2 is "+hash2s);
System.out.println("HASH 2 is "+hash2);

返回不一样的值byte[]:

HASH 1 是 V%��%�P�9�P��v�/�/e\BF}�$]

哈希 1 是 [B@629f0666

HASH 2 是 V%��%�P�9�P��v�/�/e\BF}�$]

哈希 2 是 [B@1bc6a36e

如何让相同的 byte[] 成为 AES-256 的密钥?

【问题讨论】:

    标签: java hash


    【解决方案1】:

    [B@629f0666[B@1bc6a36e 事物分别不是 hashhash2 的内容,它们是它们的默认 toString() 表示形式。 [B 部分告诉你它是一个字节数组,后面的十六进制数是它的身份哈希码,类似于内存中的地址。 (不完全是地址,但这样想是有用的。)

    当然,由于它们是两个不同的数组,它们位于内存中的不同位置,因此它们的默认toString() 表示不同。但这无关紧要:它们的内容是相同的。

    为了查看它们是否相同,您不必打印它们,您可以简单地逐字节比较它们。但是如果你坚持打印它们,你对new String( hash2, StandardCharsets.UTF_8 ); 的尝试是错误的,因为它试图将随机字节重新解释为 unicode 字符,这当然会产生有趣的结果。看看这个答案:How to convert a byte array to a hex string in Java?

    (无论如何,请注意这两个垃圾字符串是相同的,所以这应该告诉您您的字节数组也是相同的。)

    【讨论】:

      【解决方案2】:

      您需要在连续使用同一对象之间调用messageDigest.reset() 来计算不同数据的哈希值。

      这是因为MessageDigest 旨在与您提供给它的数据块一起使用,而不是一次性提供给它(通过调用update(...))。所以行为是不断更新内部哈希,直到您通过reset() 重置状态。

      基本上在您的代码中,第二个摘要用于字符串 "ALIBABAALIBABA"

      【讨论】:

      • 但是为什么仍然有相同的字符串散列
      • 因为您没有将byte[] 数组转换为它的文字String 表示,所以您将byte[] 解释为UTF-8 String 对象。但这没有任何意义,因为摘要不是String,而是数值。试试System.out.println(Arrays.toString(hash2));
      • 那么你没有正确地做事或者你没有发布你的确切代码。你应该注意你发布的内容,这绝对有效:ideone.com/S36oUA
      【解决方案3】:

      有人可能需要更简单的解释。 String 不仅包含其中的字符信息,还包含其他一些信息。例如,可能是关于它在字符串池中的位置等。该信息也包含在.toByteArray() 中,因此 2 个相同字符串的结果不同。一条建议是改用char[]。这是一些代码。

      byte[] toBytes(char[] chars) {
        CharBuffer charBuffer = CharBuffer.wrap(chars);
        ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
        byte[] bytes = Arrays.copyOfRange(byteBuffer.array(),
                byteBuffer.position(), byteBuffer.limit());
        Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
        return bytes;
      }
      
      ...
      
      bytesToHex(MessageDigest
                   .getInstance("SHA-256")
                   .digest(toBytes(charArray)));
      
      ...
      
      String bytesToHex(byte[] bytes){
        //any way you want to convert byte array to String
        //for example using apache.commons.codec:
        return Hex.encodeHexString(bytes);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-25
        • 2023-02-07
        • 2013-06-04
        • 1970-01-01
        • 1970-01-01
        • 2017-02-20
        • 2017-03-16
        相关资源
        最近更新 更多