散列 torrent 文件片段

Posted

技术标签:

【中文标题】散列 torrent 文件片段【英文标题】:Hashing torrent file pieces 【发布时间】:2018-10-22 16:19:27 【问题描述】:

我正在尝试计算和比较 torrent 文件的哈希值,但遇到了一个问题,即根据我的文件,我得到的哈希值比 torrent 应用程序生成的 torrent 文件中的哈希值多。

我有一个散列函数来计算文件片段的散列,每个文件都经过它

      public static async Task<IEnumerable<byte[]>> CreateHashTableAsync(HashAlgorithm provider,
        Stream inputStream,
        int blockSize,
        IBufferManager bufferManager,
        CancellationToken ct)
    
        if (provider == null)
            throw new ArgumentNullException(nameof(provider));

        if (inputStream == null)
            throw new ArgumentNullException(nameof(inputStream));

        if (bufferManager == null)
            throw new ArgumentNullException(nameof(bufferManager));

        var HASH_TABLE = new List<byte[]>();

        var BUFFER = bufferManager.TakeBuffer(blockSize);

        int CALL_READ = 0;
        while ((CALL_READ = await inputStream.ReadAsync(BUFFER, 0, blockSize, ct).ConfigureAwait(false)) > 0)
                        
            ct.ThrowIfCancellationRequested();
            var BLOCK_HASH = provider.ComputeHash(BUFFER, 0, CALL_READ);
            HASH_TABLE.Add(BLOCK_HASH);
        

        BUFFER = null;

        return HASH_TABLE;

    

正如我所说,问题是在所有文件的散列结束时,我的碎片比种子文件多一点。 我应该以不同的方式处理散列吗? 我知道在文件末尾通常是文件中剩余的数据小于块大小,但不知道应该如何处理这种情况。

【问题讨论】:

您的List&lt;byte[]&gt; 不是“哈希表”。此外,使用UPPER_CASE 标识符也不是惯用的 C# 标识符,它通常在 C 和 C++ 中用于表示预处理器宏和常量,但您将它们用于变量。 感谢您注意到这一点,但它与原始问题有何关系? 这与您的实际问题无关,但我将其作为有用的评论提供。 老实说,由于某些奇怪的原因,它开始使用带有大写字母的局部变量,它帮助我将局部变量与输入变量分开。那是一件坏事吗? :) 我认为当其他人遇到您的代码时这样做是一件坏事,因为绝大多数 C# 程序员都遵守约定,将camelCase 用于方法参数和局部变量。 C# 仅将 UPPER_CASE 标识符用于预处理器 #define#if 符号 - 所以你最终只会混淆阅读你代码的其他人。 【参考方案1】:

这将是一个正确的方法:

+-----------------+-----------------+-----------------+-----------------+
| Piece 0         | Piece 1         | Piece 2         | Piece 3         |
+-----------------+-----------------+-----------------+-----------------+
| File A                   | File B                        | <- file B does not end at the end of piece 3
+-----------------+-----------------+-----------------+-----------------+

这是一种不正确的做法:

+-----------------+-----------------+-----------------+-----------------+
| Piece 0         | Piece 1         | Piece 2         | Piece 3         |
+-----------------+-----------------+-----------------+-----------------+
| File A                   |00000000| File B                        |000| 
+-----------------+-----------------+-----------------+-----------------+

【讨论】:

是的,我确实怀疑这一点,所以在这种重叠的情况下,我需要用第一个文件中的数据填充散列字节数组,然后是下一个文件,然后才对其执行散列函数?例如块大小 1024 字节 1000 字节从 first 和 24 字节从 next ,然后执行散列? 是的,将 torrent 数据(无论其中有多少文件)想象成一个连续的字节数组,其顺序与 torrent 信息文件中指定的顺序相同。 在本地保存下载的片段或响应远程对等点的片段请求时,您还必须特别注意他,这意味着您可能需要将片段中的字节保存到超过一个文件或从多个文件中读取一个字节。 不客气。我还注意到您正在严格测试您的方法输入,这始终是一件好事。如果您想让您的工作更轻松、更快捷,您可能需要查看防御性编程框架github.com/aljazsim/defensive-programming-framework-for-net。【参考方案2】:

你对这一行有一个错误的假设:

(CALL_READ = await inputStream.ReadAsync(BUFFER, 0, blockSize, ct)

Stream.Read 不保证blockSize-many bytes 实际上会被读取,您应该在对ReadAsync 的调用完成后检查CALL_READ == blockSize 是否完成,如果没有,那么您应该处理这种情况具体来说。

【讨论】:

holly molly 你说得对,可能是这样,让我纠正一下,看看它是否能解决问题

以上是关于散列 torrent 文件片段的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 .torrent 文件?

使用 libtorrent 下载特定片段

如何验证 torrent Infohash 是不是有效?

使用 python-libtorrent 从 torrent 文件中获取 torrent 下载目录

使用 c# 将 Torrent Magnet 链接转换为 .torrent 文件

在torrent文件中设置torrent上载的大小