为什么散列信息字典会出错?
Why is hashing the info dict turning out wrong?
多年来,我一直在努力让 BitTorrent 的哈希算法在 Java 中运行,但它总是出错。
我已将其缩小到几行代码,我 99% 确定问题是:
Bencode bencode = new Bencode(Charset.forName("UTF-8"));
byte[] fileBytes = new byte[33237];
Map<String, Object> dict = bencode.decode(fileBytes, Type.DICTIONARY);
Map infoMap = (Map) object.get("info");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BencodeOutputStream bos = new BencodeOutputStream(baos);
bos.writeDictionary(infoMap);
byte[] hash = DigestUtils.sha1(baos.toByteArray());
我对数组的大小进行了硬编码,以确保问题不是由周围的一堆零引起的。
我试过 UTF-8
和 US-ASCII
。
我已经尝试使用两个不同的库进行编码,所以它可能不在问题所在的位置。
编辑: 从规范来看,信息字典似乎应该被编码为 info_hash。因此,我尝试将字典写成 ByteArrayOutputStream
,然后对 ByteArrayOutPutStream
持有的 byte[]
进行 sha1 哈希处理。
DigestUtils.sha1
方法会提供URL编码器吗?找不到任何相关信息。
正如 Encombe 指出的那样,问题出在编码上。在 Bencode 规范中,它谈到了 字节字符串 ,这似乎表明它只是一个没有任何编码的数据流。
我查看的两个库都将所有字节字符串转换为某种编码,因此我编写了一个 Bencode 库,它只在特别要求时才进行转换。
上面的代码基本上是正确的,但这是我现在使用的客户端代码:
public void readManifest() throws IOException, Exception {
byte[] fileBytes = FileUtils.readFileToByteArray(file);
ByteArrayInputStream bis = new ByteArrayInputStream(fileBytes);
BDecoder decoder = new BDecoder(bis, "UTF-8");
BDict dict = decoder.decodeDict();
Map<String, Object> valueMap = dict.getValue();
infoMap = (Map<String, Object>) valueMap.get("info");
}
public String hash() throws Exception {
if (hash == null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BEncoder encoder = new BEncoder(baos, "UTF-8");
encoder.encodeDict(infoMap);
hash = DigestUtils.sha1Hex(baos.toByteArray());
}
return hash;
}
多年来,我一直在努力让 BitTorrent 的哈希算法在 Java 中运行,但它总是出错。
我已将其缩小到几行代码,我 99% 确定问题是:
Bencode bencode = new Bencode(Charset.forName("UTF-8"));
byte[] fileBytes = new byte[33237];
Map<String, Object> dict = bencode.decode(fileBytes, Type.DICTIONARY);
Map infoMap = (Map) object.get("info");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BencodeOutputStream bos = new BencodeOutputStream(baos);
bos.writeDictionary(infoMap);
byte[] hash = DigestUtils.sha1(baos.toByteArray());
我对数组的大小进行了硬编码,以确保问题不是由周围的一堆零引起的。
我试过 UTF-8
和 US-ASCII
。
我已经尝试使用两个不同的库进行编码,所以它可能不在问题所在的位置。
编辑: 从规范来看,信息字典似乎应该被编码为 info_hash。因此,我尝试将字典写成 ByteArrayOutputStream
,然后对 ByteArrayOutPutStream
持有的 byte[]
进行 sha1 哈希处理。
DigestUtils.sha1
方法会提供URL编码器吗?找不到任何相关信息。
正如 Encombe 指出的那样,问题出在编码上。在 Bencode 规范中,它谈到了 字节字符串 ,这似乎表明它只是一个没有任何编码的数据流。
我查看的两个库都将所有字节字符串转换为某种编码,因此我编写了一个 Bencode 库,它只在特别要求时才进行转换。
上面的代码基本上是正确的,但这是我现在使用的客户端代码:
public void readManifest() throws IOException, Exception {
byte[] fileBytes = FileUtils.readFileToByteArray(file);
ByteArrayInputStream bis = new ByteArrayInputStream(fileBytes);
BDecoder decoder = new BDecoder(bis, "UTF-8");
BDict dict = decoder.decodeDict();
Map<String, Object> valueMap = dict.getValue();
infoMap = (Map<String, Object>) valueMap.get("info");
}
public String hash() throws Exception {
if (hash == null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BEncoder encoder = new BEncoder(baos, "UTF-8");
encoder.encodeDict(infoMap);
hash = DigestUtils.sha1Hex(baos.toByteArray());
}
return hash;
}