Objective-C iOS 从 Torrent 文件生成 Info_Hash
Objective-C iOS Generating Info_Hash from Torrent File
我目前正在努力尝试从我下载的 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]];
}
}
这是我第一次使用 Torrents 和编码。我知道我只应该对主词典中包含的 "info" 词典进行编码。
有谁知道我这里可能哪里出错了?
实际pieces
内容是数据:
0xa9, 0x4a, 0x8f, 0xe5, 0xcc, 0xb1, 0x9b, 0xa6, 0x1c, 0x4c, 0x08, 0x73, 0xd3, 0x91, 0xe9, 0x87, 0x98, 0x2f, 0xbb, 0xd3
如@Encombe 所述,这是 SHA1 哈希。
来自维基百科:
The specification does not deal with encoding of characters outside the ASCII set; to mitigate this, some BitTorrent applications explicitly communicate the encoding (most commonly UTF-8) in various non-standard ways.
而pieces
是十六进制数据,不是UTF-8。
我终于找到了解决这个问题的方法。大家都怀疑是编码问题。
我按照此 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
对象。这避免了我遇到的编码问题并生成正确的散列。
不是最优雅的解决方案,但我很高兴它有效。
我目前正在努力尝试从我下载的 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]];
}
}
这是我第一次使用 Torrents 和编码。我知道我只应该对主词典中包含的 "info" 词典进行编码。
有谁知道我这里可能哪里出错了?
实际pieces
内容是数据:
0xa9, 0x4a, 0x8f, 0xe5, 0xcc, 0xb1, 0x9b, 0xa6, 0x1c, 0x4c, 0x08, 0x73, 0xd3, 0x91, 0xe9, 0x87, 0x98, 0x2f, 0xbb, 0xd3
如@Encombe 所述,这是 SHA1 哈希。
来自维基百科:
The specification does not deal with encoding of characters outside the ASCII set; to mitigate this, some BitTorrent applications explicitly communicate the encoding (most commonly UTF-8) in various non-standard ways.
而pieces
是十六进制数据,不是UTF-8。
我终于找到了解决这个问题的方法。大家都怀疑是编码问题。
我按照此 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
对象。这避免了我遇到的编码问题并生成正确的散列。
不是最优雅的解决方案,但我很高兴它有效。