【问题标题】:Why dropping leading all zeros byte in a java byte array before hashing为什么在散列之前在 java 字节数组中删除前导全零字节
【发布时间】:2017-05-07 00:27:55
【问题描述】:

这个问题是关于在 java 中对字节数组进行散列之前对它们进行的操作。

我试图理解为什么在多个 srp 加密库中,前导零字节(如果有的话)在被散列之前被丢弃。

例如:这是来自充气城堡

/**
 * Return the passed in value as an unsigned byte array.
 *
 * @param value value to be converted.
 * @return a byte array without a leading zero byte if present in the signed encoding.
 */
public static byte[] asUnsignedByteArray(int length, BigInteger value)
{
    byte[] bytes = value.toByteArray();
    if (bytes.length == length)
    {
        return bytes;
    }

    int start = bytes[0] == 0 ? 1 : 0;
    int count = bytes.length - start;

    if (count > length)
    {
        throw new IllegalArgumentException("standard length exceeded for value");
    }

    byte[] tmp = new byte[length];
    System.arraycopy(bytes, start, tmp, tmp.length - count, count);
    return tmp;
}

或者这是来自 nimbus SRP:

public static byte[] toUnsignedByteArray(final BigInteger bigInteger) {

    byte[] bytes = bigInteger.toByteArray();
    byte[] result = toUnsignedByteArray(bytes);

    // remove leading zero if any
    if (bytes[0] == 0) {

        byte[] tmp = new byte[bytes.length - 1];

        System.arraycopy(bytes, 1, tmp, 0, tmp.length);

        return tmp;
    }
    return bytes;
}

购买的示例基本上会去掉前导零。这些库中的方法称为“toUnsignedByteArray”,尽管我不明白为什么删除前导零会使字节数组无符号。 IE。它只丢弃零字节,然后下一个字节可能是负数,即下一个字节成为最左边的字节(在 Big Indian 中),字节中最左边的位是符号位,可以根据字节设置或取消设置,所以如果我正确理解了字节数组的结构,那么首先不应将这些方法调用为“toUnsignedByteArray”。然而最重要的问题是为什么我们需要删除那个零字节以防它全为零

这是来自 srp rfc 5054 附录 A 的测试向量示例。我们从 A 和 B 计算 U。其中 B 的零字节恰好是二进制中的全零,即如果我们将 B 作为字节数组打印,我们将得到以下值

public static final B = new BigInteger("BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC996C6DA04453728610D0C6DDB58B318885D7D82C7F8DEB75CE7BD4FBAA37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAEEB4012B7D7665238A8E3FB004B117B58", 16);

[0, -67, 12, 97, 81, 44, 105, 44, 12, -74, -48, 65, -6, 1, -69, 21, 45、73、22、-95、-25、122、-12、106、-31、5、57、48、17、-70、-13、 -119、100、-36、70、-96、103、13、-47、37、-71、90、-104、22、82、35、111、-103、-39、-74、-127、 -53, -8, 120, 55, -20, -103, 108, 109, -96, 68、83、114、-122、16、-48、-58、-35、-75、-117、49、-120、-123、-41、 -40、44、127、-115、-21、117、-50、123、-44、-5、-86、55、8、-98、111、-100、96、89、-13、-120 , -125, -114, 122, 0, 3, 11, 51, 30, -73, 104, 64, -111, 4, 64, -79, -78, 122, -82, -82, -21, 64、18、-73、-41、102、 82、56、-88、-29、-5、0、75、17、123、88]

以二进制打印的字节零:00000000

现在我明白由于某种原因删除该字节很重要(尽管我不确定)我的意思是因为这些测试向量使用这两个库正确计算它应该正确编程对吗?但是我不明白为什么我们需要删除前导零字节。它有什么问题。如果我删除前导 zeor 字节并尝试从没有前导零字节的字节数组中创建另一个 BigInteger,那么在这种情况下我将得到一个完全不同的数字,甚至是负数。所以删除那个零字节对我来说没有任何意义。欢迎任何解释。

【问题讨论】:

    标签: arrays hash cryptography srp-protocol


    【解决方案1】:

    名称中的“未签名”可能有点误导;不是删除 0 字节使其无符号,它只是假设 BigInteger 包含一个无符号数。

    在这些情况下丢弃的 0 字节不会更改值,就像 010011 的值相同。

    出于各种原因,删除零很重要:

    1. 不要用不必要的 0 字节浪费空间。
    2. 在比较字节数组时使表示保持一致。
    3. (在您所指的上下文中最相关)前面带有额外 0 的字节数组的哈希与没有额外 0 的字节数组的哈希不同。哈希函数不毕竟我不知道这是一个数字,在这种情况下 0 是没有意义的。想象一下,如果这是一个带有字节 0:1:2:3 的文件与带有字节 1:2:3 的文件。您不会期望不同长度的文件的哈希值相同。

    另请注意,是从开头还是结尾删除 0 字节取决于整数表示的 endianness

    更新:澄清删除 0 字节:

    虽然从任何旧字节数组的开头或结尾删除一个 0 字节更改值,但在您所指的情况下,我们谈论的是整数的表示。如果 0 字节很重要,例如如果您想往返一些二进制数据,则不适合将该二进制数据加载到 BigInteger 类中。我参考我原来的例子,你不会认为101 是不同的数字(尽管你会认为它们是不同的字符串)?

    更新:对字节顺序的澄清:

    整数可以在内存中以不同的方式表示。如果您看到数字20(普通十进制),您就会知道2 指的是十位数,但这只是一个约定。我们可以将 20 倒写为02,并将最大的单位放在数字的末尾。同样在计算机中,数字的顺序可以是我们通常熟悉的方式,也可以是“倒序”。鉴于此,不影响数字值的 0 可能位于字节数组的开头或结尾,我们必须知道在处理字节数组时应该以哪种方式环绕字节“阅读”。

    【讨论】:

    • 我接受数字 1 和 2,但是我对数字 3 有一些疑问。我不同意丢弃零字节不会改变值的说法。我看到的问题是,如果您删除零字节并从中取出一个字节数组并尝试将其转换回 BigInteger,那么您将不会得到相同的值,因此它确实会改变它。此外,我希望如果我从某个对象(即整数文件等)中获取哈希值,因为它们是完全相同的对象,即它们在开始时,除了确实有一些约定,就像你提到的关于字节序的依赖关系
    • 您能否详细说明字节顺序,维基百科似乎没有提及。
    • 我已经更新了对您的 2 cmets 中的点的一些说明。
    • softwariness,我又在想你的答案了,我对你的第一个答案还有一个问题,现在如何“不要用不必要的 0 字节浪费空间”。当散列的输出总是一个常数值时,这里有帮助吗?如果我有一个长度为 200 或 2000 的 BigIntger 并不重要,输出始终是恒定的,具体取决于所使用的哈希方法,还是我犯了错误?
    • 软件,你知道是否有任何 rfc 或标准描述了这种对字节序的依赖?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 2017-11-08
    • 2021-11-26
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    相关资源
    最近更新 更多