为啥散列信息字典结果错误?
Posted
技术标签:
【中文标题】为啥散列信息字典结果错误?【英文标题】:Why is hashing the info dict turning out wrong?为什么散列信息字典结果错误? 【发布时间】:2017-07-11 19:42:04 【问题描述】:多年来,我一直在尝试让 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 dict 应该被 urlencoded 为 info_hash。所以我尝试将字典写成ByteArrayOutputStream
,然后对ByteArrayOutPutStream
持有的byte[]
进行sha1 哈希处理。
DigestUtils.sha1
方法会提供 URL 编码器吗?找不到任何相关信息。
【问题讨论】:
如有疑问,请调试 我不知道你在做什么,但我查了the spec。是您要计算的info_hash
吗?它说应该是info
的值,而不是pieces
@thatotherguy 阅读时似乎是这样,是的。我尝试的时候没有用。在您看来,您是否会假设信息图已经进行了 sha1 编码?读起来好像是这样,但同时又很模糊。
信息映射被编码:“来自 Metainfo 文件的信息键值的 urlencoded 20 字节 SHA1 哈希。请注意,该值将是一个编码字典”。我如何运行您的示例?您不提供任何输入或输出数据
谢谢。看来我的代码现在正在解码大字典,获取解码的信息字典,对其进行编码,然后进行 sha1 散列。这似乎不是让它工作的合理流程吗?
【参考方案1】:
正如 Encombe 所指出的,问题在于编码。在 Bencode 规范中,它谈到了 byte strings,这似乎表明它只是一个没有任何编码的数据流。
我查看的两个库都将所有字节字符串转换为某种编码,因此我编写了一个 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;
【讨论】:
好。您可以通过将d4:infod4:name5:b.txt6:lengthi1e12:piece lengthi32768e6:pieces20:1234567890abcdefghijee
保存为 unsort_dict.torrent 来验证它是否可以处理 special case of a unsorted info-dict 它应该具有 info_hash:34FCC6C1ACC8C8A56DE3C2EF20924043CC51685E
@Encombe 我收到了那个哈希,是的。我使用的是 LinkedHashMap,因此所有内容的排序方式与读取时相同。
小提示:虽然 100% 正确的是,经过编码的“字符串”实际上是任意字节序列(BEP52 对此进行了澄清),但可以使用 ISO 8859-1 作为解决方法将它们视为字符串,因为它是 1: 1 将原始字节映射到 unicode 代码点(即 java 中的 char
值)。但这是一个 hack,因为如果这些 String
实例实际上应该是 UTF8,它将包含乱码数据。但是,如果必须通过需要字符串的 API 传递字节数据,这仍然是一个有用的技巧。以上是关于为啥散列信息字典结果错误?的主要内容,如果未能解决你的问题,请参考以下文章