2017-11-11 226 views
1

我正在努力遵循如https://en.wikipedia.org/wiki/SHA-2中所述的SHA-2加密函数。SHA 2哈希和Java的问题

我审查其说行:

  • 开始长度为L比特的原始消息附加一个单一的“1”位;
  • 附加K'0'位,其中K是最小数量> = 0,使得L + 1 + K +64是512的倍数
  • 将L附加为64位大端整数,使得总后处理长度是512位的倍数。

我不明白最后两行。如果我的字符串很短,那么在添加K'0'位后它的长度是512.我应该如何在Java代码中实现它?

回答

1

首先,应该清楚地说明所谈论的“字符串”不是Java String而是一个位串。这些算法是基于二进制/位的。该实现通常不会处理位而是字节。所以有一个翻译阶段,你应该看到字节而不是位。 (SHA-224/256)或1024位(SHA-384/512)的块运行SHA-512。所以基本上你有一个64或128字节的缓冲区,你在操作之前就已经加载了。您也可以直接在32位int字段(SHA-224/256)或64位long字段中缓存数据,因为这是所操作的字大小。

现在填充是比较简单的程序。填充称为位填充。由于它在big-endian模式下使用(SHA-2幸运地使用SHA-3中的braindead little endian模式),填充由一个字节中的最高位设置的单个位组成,其余部分由零。这使得必须放入缓冲区的值为(byte) 0x80

如果由于缓冲区已满而无法创建此填充,则必须处理先前的块,然后将现有可用缓冲区的第一位设置为(byte) 0x80。在较新的Java中,您还可以使用(byte) 0b1_0000000字节,这更明确。

现在,您只需添加零即可,直到剩余8到16个字节,这取决于所使用的散列输出大小。如果没有足够的字节,则填充直到结束,处理该块,然后重新开始填充零字节,直到再次有8或16个字节。

现在最后你必须编码的数字,用你剩下的8或16个字节。因此,请将您的输入乘以8,并确保按照您所期望的Java中最低有效位尽可能多的方式对这些字节进行编码。如果您不想自己编程,可能需要使用https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#putLong-long-。无论如何,你可能会忘记超过2^56字节的任何内容,所以如果你有SHA-384/SHA-512,那么简单地将前八个字节设置为零。

就是这样,除了您仍然需要处理最后一个块,然后根据您的特定输出大小,从左侧使用尽可能多的字节。

+0

请注意,Bouncy Castle和Java源代码都可用。有时他们不太容易阅读,所以我一直很好,并描述它。 –