Objective-C iOS 从 Torrent 文件生成 Info_Hash

Posted

技术标签:

【中文标题】Objective-C iOS 从 Torrent 文件生成 Info_Hash【英文标题】:Objective-C iOS Generating Info_Hash from Torrent File 【发布时间】:2015-02-28 14:56:53 【问题描述】:

我目前正在努力从我下载的 torrent 文件中生成 info_hash。我使用 uTorrent 创建了 Torrent 文件,并使用 PeerTracker 作为我的跟踪软件。

我正在使用此处找到的代码的更新版本:https://code.google.com/p/rouge-server/source/browse/trunk/driver/objective-c/RougeDriver/BEncoding.m?r=88


    announce = "http://sub.url.com:8080/announce.php";
    "created by" = "uTorrent/1870";
    "creation date" = 1425134140;
    encoding = "UTF-8";
    info =     
        length = 4;
        name = "test.txt";
        "piece length" = 16384;
        pieces = "\U00a9J\U00e8\U00c2\U00c3\U00b1\U00f5\U00b6L\bs\U201d\U00eb\U00c8\U00e1\U00f2/\U00aa\U201d";
    ;

以下是我使用的确切编码方法:

+ (void)encode:(id)object toString:(NSMutableString *)string

    if([object isKindOfClass:[NSDictionary class]])
    
        NSDictionary *dictionary = (NSDictionary *)object;
        [string appendString:@"d"];

        for(id key in [dictionary allKeys])
        
            [self encode:key toString:string];
            [self encode:[dictionary objectForKey:key] toString:string];
        

        [string appendString:@"e"];
    
    else if([object isKindOfClass:[NSString class]])
    
        NSString *stringObject = (NSString *)object;
        NSString *format = @"%lu:%@";

        [string appendFormat:format, [string length], stringObject];
    
    else if([object isKindOfClass:[NSArray class]])
    
        NSArray *array = (NSArray *)object;
        [string appendString:@"l"];

        for(id item in array)
        
            [self encode:item toString:string];
        

        [string appendString:@"e"];
    
    else if([object isKindOfClass:[NSNumber class]])
    
        NSNumber *number = (NSNumber *)object;
        NSString *format = @"i%de";

        [string appendFormat:format, [number intValue]];
    

这是我第一次使用 Torrent 和 Bencoding。我知道我只应该对包含在主字典中的“信息”字典进行编码。

有谁知道我在这里可能出错的地方吗?

【问题讨论】:

pieces 似乎不是 UTF-8,而是包含 UTF-16 的混合:“\U00a9”似乎是“©”的 UTF-16 字符编码。 我需要什么来删除它?是在解码吗?还是编码? 我没有说你需要删除任何东西。在问题中:"encoding = "UTF-8" but many characters似乎是UTF-16。似乎有不匹配。 目前我正在下载文件并使用 NSData dataFromContentsOfUrl 打开它。为了测试,我现在使用 BitTorrent 和 uTorrent 创建了 torrent。两者都声称使用 UTF-8 进行编码,但在片段部分的开头都有“©”。 它只是在 torrent 文件中以 UTF-8 编码的任何文本。 pieces 数据是一块数据的原始 20 字节二进制 SHA1 散列的字节串,这些散列数据相互连接在一起。 【参考方案1】:

pieces的实际内容是数据:

0xa9, 0x4a, 0x8f, 0xe5, 0xcc, 0xb1, 0x9b, 0xa6, 0x1c, 0x4c, 0x08, 0x73, 0xd3, 0x91, 0xe9, 0x87, 0x98, 0x2f, 0xbb, 0xd3

正如@Encombe 所说,这是 SHA1 哈希。

来自***:

该规范不处理 ASCII 集之外的字符编码;为了缓解这种情况,一些 BitTorrent 应用程序以各种非标准方式显式地传达编码(最常见的是 UTF-8)。

pieces 是十六进制数据,而不是 UTF-8。

【讨论】:

但是我不是要对整个“信息”字典进行编码以生成我可以宣布的 info_hash 吗?或者在对信息字典进行编码之前,我需要对这段数据做些什么特别的事情? ***的文章有点过时了。 The BitTorrent Protocol Specification - BEP3 已更新,现在明确声明 UTF-8。 也许这个答案会有所帮助:***.com/questions/19749085/… @Encombe 我的第一条评论是它包含 UTF-16。 pieces 数据不是 UTF-8。显示的pieces 值不正确,请参阅此答案中的数据。 非常感谢你们的帮助。它一定与编码有关。我现在重新按照链接 Encombe 中的说明进行操作,而不是保存到 NSString 或任何内容,我实际上只是将信息字典的每个字节附加到 NSMutableData 实例,然后是 SHA1。这每次都会给出正确的结果。我不必担心编码,因为它的编码与主 torrent 文件中的编码相同。再次感谢!【参考方案2】:

我终于找到了解决这个问题的方法。每个人都怀疑这是一个编码问题。

我按照此 SO 中的说明进行操作: Calculating the info-hash of a torrent file

不过,我做了一个小调整:

+ (NSDictionary *)decodeDictionary:(HTData *)data

    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

    [data getNextCharacter];

    while([data showNextCharacter] != 'e')
    
        NSString *key = [self decodeString:data];

        id object;

        if([key isEqualToString:@"info"])
        
            NSInteger startIndex = [data getCurrentIndex];
            NSInteger endIndex;
            object = [self decodeNextObject:data];

            endIndex = [data getCurrentIndex];

            NSMutableData *charData = [[NSMutableData alloc] init];

            for(NSInteger i = startIndex; i < endIndex; i++)
            
                char c = [data charAtIndex:i];
                [charData appendBytes:&c length:1];
            

            NSData *hashedInfo = [charData SHA1];

            [dictionary setObject:hashedInfo forKey:@"info_hash"];
        
        else
        
            object = [self decodeNextObject:data];
        

        [dictionary setObject:object forKey:key];
    

    [data getNextCharacter];

    return dictionary;
 

我现在正在字典解码器中计算哈希值。我还在使用单个 chars 并将它们直接附加到 NSMutableData 对象。这避免了我遇到的编码问题并生成了正确的哈希。

不是最优雅的解决方案,但我很高兴它有效。

【讨论】:

以上是关于Objective-C iOS 从 Torrent 文件生成 Info_Hash的主要内容,如果未能解决你的问题,请参考以下文章

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

如何从Javascript调用Objective-C方法并将数据发送回iOS中的Javascript?

IOS/Objective-C:从 NSManagedObject 构建 NSDictionary

从 iOS 中的私钥派生的证书(Objective-C)

无法从 Objective-C 视图控制器访问 Swift var - iOS

Objective-C/iOS:如何从 CoreData 中的属性中删除“值”?