无效的info_hash(Java BitTorrent客户端)

时间:2012-11-03 23:03:01

标签: java sha1 bittorrent

根据规范:http://wiki.theory.org/BitTorrentSpecification

  

info_hash:urlencoded来自Metainfo文件的信息密钥值的20字节SHA1哈希值。请注意,根据上面信息键的定义,该值将是一个bencoded字典。

torrentMap是我的字典,我得到info密钥,这是另一个字典,我计算哈希值,我URLencode

但是当我尝试将其发送给跟踪器时,我总是收到invalid info_hash消息。

这是我的代码:

    public String GetInfo_hash() {
    String info_hash = "";

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutput out = null;
    try {
        out = new ObjectOutputStream(bos);
        out.writeObject(torrentMap.get("info"));
        byte[] bytes = bos.toByteArray();        //Map => byte[]

        MessageDigest md = MessageDigest.getInstance("SHA1");
        info_hash = urlencode(md.digest(bytes));  //Hashing and URLEncoding

        out.close();
        bos.close();

    } catch (Exception ex) {        }

    return info_hash;
}

private String urlencode(byte[] bs) {
    StringBuffer sb = new StringBuffer(bs.length * 3);
    for (int i = 0; i < bs.length; i++) {
        int c = bs[i] & 0xFF;
        sb.append('%');
        if (c < 16) {
            sb.append('0');
        }
        sb.append(Integer.toHexString(c));
    }
    return sb.toString();
}

1 个答案:

答案 0 :(得分:0)

这几乎肯定是问题所在:

out = new ObjectOutputStream(bos);
out.writeObject(torrentMap.get("info"));

您要进行哈希处理的是torrentMap.get("info")值的 Java二进制序列化格式。我发现很难相信所有BitTorrent程序都是为了了解它。

我从规范中不能立即清楚“info”键的值是什么,但你需要找出一些其他的方法将它变成一个字节数组。如果它是一个字符串,我希望有一些明确指定的编码(例如UTF-8)。如果它已经是二进制数据,那么直接使用该字节数组。

编辑:实际上,听起来这个值将是一个“bencoded dictionary”,根据你的引用,看起来它将是一个字符串。在散列之前,你是如何编码该字符串的(例如,它听起来可能包含非ASCII字符串的值)。如果您的示例字符串都是ASCII,那么使用“ASCII”和“UTF-8”作为String.getBytes(...)的编码名称无论如何都会得到相同的结果......当然......