为什么散列信息字样错误?

时间:2017-07-11 19:42:05

标签: java bittorrent bencoding

我已经尝试了很长时间才能让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-8US-ASCII

我已尝试使用两个不同的库进行编码,因此可能不存在问题所在。

修改:从规范中看,信息字典似乎应该被urlencoded为info_hash。所以我尝试将字典写入ByteArrayOutputStream,然后对byte[]持有的ByteArrayOutPutStream进行sha1散列。

DigestUtils.sha1方法是否会提供网址编码器?找不到任何相关信息。

1 个答案:

答案 0 :(得分:1)

正如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;
}