我尝试比较2字节数组。
字节数组1是一个数组,其中包含sha1哈希的最后3个字节:
private static byte[] sha1SsidGetBytes(byte[] sha1)
{
return new byte[] {sha1[17], sha1[18], sha1[19]};
}
字节数组2是一个数组,我填充了来自十六进制字符串的3个字节:
private static byte[] ssidGetBytes(String ssid)
{
BigInteger ssidBigInt = new BigInteger(ssid, 16);
return ssidBigInt.toByteArray();
}
这种比较怎么可能:
if (Arrays.equals(ssidBytes, sha1SsidGetBytes(snSha1)))
{
}
大部分时间都有效,但有时却没有。字节顺序?
e.g。对于“6451E6”(十六进制字符串)它工作正常,对于“ABED74”它没有...
答案 0 :(得分:3)
如果你试试这个问题很明显:
BigInteger b1 = new BigInteger("6451E6", 16);
BigInteger b2 = new BigInteger("ABED74", 16);
System.out.println(b1.toByteArray().length);
System.out.println(b2.toByteArray().length);
具体来说,ABED74创建一个BigInteger,其字节数组长度为4个字节 - 所以当然它不会等于任何三个字节数组。
直接的解决方法是更改ssidGetBytes
中的返回语句
return ssidBigInt.toByteArray();
到
byte[] ba = ssidBigInt.toByteArray();
return new byte[] { ba[ba.length - 3], ba[ba.length - 2], ba[ba.length - 1] };
答案 1 :(得分:1)
你通过BigInteger解析十六进制字符串的方法基本上是有缺陷的。例如,new BigInteger("ABED74").toByteArray()
返回 4 字节的数组,而不是三个。虽然你可以解决这个问题,但你基本上不试图做任何涉及BigInteger值的事情......你只是想解析十六进制。
我建议您使用Apache Codec库进行解析:
byte[] array = (byte[]) new Hex().decode(text);
(Apache Codec的API留下了一些需要的东西,但确实有效。)
答案 2 :(得分:1)
来自javadoc(强调我的):
http://download.oracle.com/javase/1.5.0/docs/api/java/math/BigInteger.html#toByteArray%28%29
返回包含的字节数组 二进制补码表示 这个BigInteger。字节数组将 处于大端字节顺序:最多 重要的字节在第0个 元件。该数组将包含 所需的最小字节数 代表这个BigInteger,包括 至少有一个符号位,即 (ceil((this.bitLength()+ 1)/ 8))。 (这种表示是兼容的 使用(byte [])构造函数。)
你正在使用的ByteInteger(String,radix)构造函数中有很多计算,这并不能保证构造的BigInteger会产生一个字节数组(通过它的toByteArray()方法)与结果相当String的getBytes()编码。
toByteArray()的输出旨在(主要)用作BigInteger的(byte [])构造函数的输入。它不能保证除此之外的用途。
看起来像这样:toByteArray()的输出是BigInteger对象的字节表示,其中的所有内容包括内部属性,如幅度。这些属性在输入String中不存在,但是在构造BitInteger对象期间计算。
这与输入String 的字节表示不兼容,后者仅包含用于创建BigInteger的初始数值。