SHA 2 哈希和 Java 的问题
Problems with SHA 2 Hashing and Java
我正在努力遵循 https://en.wikipedia.org/wiki/SHA-2 中所述的 SHA-2 加密功能。
我正在检查以下行:
- 从长度为 L 位的原始消息开始,附加一个“1”位;
- 附加 K 个“0”位,其中 K 是最小数 >= 0,使得 L + 1 + K + 64 是 512 的倍数
- 将 L 添加为 64 位大端整数,使 post 处理的总长度成为 512 位的倍数。
最后两行我没看懂。如果我的字符串很短,它的长度在添加 K'0' 位后可以是 512。我应该如何在 Java 代码中实现它?
首先要明确一点,这里所说的"string"并不是JavaString
而是一个位串。这些算法基于 binary/bit。该实现通常不会处理位,而是处理字节。所以有一个翻译阶段,您应该看到字节而不是位。
SHA-512 在 512 位 (SHA-224/256) 或 1024 位 (SHA-384/512) 的块中运行。所以基本上你有一个 64 或 128 字节的缓冲区,你在操作之前填充它。您也可以直接将数据缓存在 32 位 int
字段(SHA-224/256)或 64 位 long
字段中,因为这是操作的字长。
现在db2的程序比较简单。填充称为位填充。由于它用于大端模式(SHA-2 幸运地使用它而不是 SHA-3 中的 braindead 小端模式),填充由一个字节中最高位设置的单个位组成,其余填充为零的。这使得必须将值 (byte) 0x80
放入缓冲区。
如果由于缓冲区已满而无法创建此填充,则您将不得不处理前一个块,然后将现在可用缓冲区的第一位设置为 (byte) 0x80
。在较新的 Java 中也可以使用 (byte) 0b1_0000000
byte 的方式,这样更显式。
现在您只需添加零,直到剩下 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 然后简单地将前八个字节设置为零。
仅此而已,除了您仍然需要处理最后一个块,然后根据您的特定输出大小从左侧开始使用尽可能多的字节。
我正在努力遵循 https://en.wikipedia.org/wiki/SHA-2 中所述的 SHA-2 加密功能。
我正在检查以下行:
- 从长度为 L 位的原始消息开始,附加一个“1”位;
- 附加 K 个“0”位,其中 K 是最小数 >= 0,使得 L + 1 + K + 64 是 512 的倍数
- 将 L 添加为 64 位大端整数,使 post 处理的总长度成为 512 位的倍数。
最后两行我没看懂。如果我的字符串很短,它的长度在添加 K'0' 位后可以是 512。我应该如何在 Java 代码中实现它?
首先要明确一点,这里所说的"string"并不是JavaString
而是一个位串。这些算法基于 binary/bit。该实现通常不会处理位,而是处理字节。所以有一个翻译阶段,您应该看到字节而不是位。
SHA-512 在 512 位 (SHA-224/256) 或 1024 位 (SHA-384/512) 的块中运行。所以基本上你有一个 64 或 128 字节的缓冲区,你在操作之前填充它。您也可以直接将数据缓存在 32 位 int
字段(SHA-224/256)或 64 位 long
字段中,因为这是操作的字长。
现在db2的程序比较简单。填充称为位填充。由于它用于大端模式(SHA-2 幸运地使用它而不是 SHA-3 中的 braindead 小端模式),填充由一个字节中最高位设置的单个位组成,其余填充为零的。这使得必须将值 (byte) 0x80
放入缓冲区。
如果由于缓冲区已满而无法创建此填充,则您将不得不处理前一个块,然后将现在可用缓冲区的第一位设置为 (byte) 0x80
。在较新的 Java 中也可以使用 (byte) 0b1_0000000
byte 的方式,这样更显式。
现在您只需添加零,直到剩下 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 然后简单地将前八个字节设置为零。
仅此而已,除了您仍然需要处理最后一个块,然后根据您的特定输出大小从左侧开始使用尽可能多的字节。