2010-04-03 2 views
21

У меня есть обзор для ответа на этот вопрос, но я только могу найти программное обеспечение, которое сделает это за вас. Кто-нибудь знает, как это сделать в python?Извлеките хэш SHA1 из торрент-файла

+5

торрент файл хранит SHA1, каждые * штуки * общих файлов и SHA1 метаданных torrent * (метафонический хеш) *. Какой хэш вы хотите точно? –

+0

Это будет хэш для каждой части. Не содержит ли файл хеш для завершенного файла для проверки ошибок? – 2010-04-03 20:31:41

+2

Некоторые .torrent-файлы содержат хеш-файл md5 для каждого файла, но это дополнительное расширение для формата файла. Хэш хэшей может использоваться для проверки правильности файлов. Вы просто проверяете, есть ли все части, и все ли они имеют правильный хеш. –

ответ

27

я написал кусок кода Python, который проверяет хэши загруженных файлов против того, что это в .torrent файл. Предполагая, что вы хотите проверить загрузку для коррупции, вы можете найти это полезным.

Для этого вам нужен bencode package. Bencode - это формат сериализации, используемый в файлах .torrent. Он может сортировать списки, словари, строки и номера, похожие на JSON.

код принимает хешей, содержащиеся в строке info['pieces']:

torrent_file = open(sys.argv[1], "rb") 
metainfo = bencode.bdecode(torrent_file.read()) 
info = metainfo['info'] 
pieces = StringIO.StringIO(info['pieces']) 

Эта строка содержит последовательность из 20 байт хешей (по одному для каждой части). Затем эти хэши сравниваются с хешем частей файла (ов) на диске.

Единственная сложная часть этого кода обрабатывает потоки нескольких файлов, так как один поток кусок может охватывать более одного файла (внутренне BitTorrent рассматривает загрузки нескольких файлов в один непрерывный файл). Я использую функцию генератора pieces_generator(), чтобы отвлечь это.

Возможно, вы захотите прочитать BitTorrent spec, чтобы понять это более подробно.

Полный код ниже:

import sys, os, hashlib, StringIO, bencode 

def pieces_generator(info): 
    """Yield pieces from download file(s).""" 
    piece_length = info['piece length'] 
    if 'files' in info: # yield pieces from a multi-file torrent 
     piece = "" 
     for file_info in info['files']: 
      path = os.sep.join([info['name']] + file_info['path']) 
      print path 
      sfile = open(path.decode('UTF-8'), "rb") 
      while True: 
       piece += sfile.read(piece_length-len(piece)) 
       if len(piece) != piece_length: 
        sfile.close() 
        break 
       yield piece 
       piece = "" 
     if piece != "": 
      yield piece 
    else: # yield pieces from a single file torrent 
     path = info['name'] 
     print path 
     sfile = open(path.decode('UTF-8'), "rb") 
     while True: 
      piece = sfile.read(piece_length) 
      if not piece: 
       sfile.close() 
       return 
      yield piece 

def corruption_failure(): 
    """Display error message and exit""" 
    print("download corrupted") 
    exit(1) 

def main(): 
    # Open torrent file 
    torrent_file = open(sys.argv[1], "rb") 
    metainfo = bencode.bdecode(torrent_file.read()) 
    info = metainfo['info'] 
    pieces = StringIO.StringIO(info['pieces']) 
    # Iterate through pieces 
    for piece in pieces_generator(info): 
     # Compare piece hash with expected hash 
     piece_hash = hashlib.sha1(piece).digest() 
     if (piece_hash != pieces.read(20)): 
      corruption_failure() 
    # ensure we've read all pieces 
    if pieces.read(): 
     corruption_failure() 

if __name__ == "__main__": 
    main() 
+0

Не знаю, решила ли эта проблема ОП, но она определенно решила мою проблему (как только я преодолел нарушенность пакета bencode: http://stackoverflow.com/questions/2693963/importing-bittorrent-bencode-module). Благодаря! –

+0

Я всегда хотел иметь такой инструмент и собирался вникать в старый официальный клиент python, чтобы узнать, как его написать. Благодаря!! – netvope

-2

Согласно this, вы должны быть в состоянии найти md5sums файлов с помощью функции поиска для части данных, которая выглядит как:

d[...]6:md5sum32:[hash is here][...]e

(SHA не входит в спецификацию)

+1

Просто найдите SHA на странице, с которой вы связались, и увидите, что она широко используется. Также цитируйте: 'md5sum: (необязательно) 32-символьный hex [...] Это вообще не используется BitTorrent, но оно включено в некоторые программы. –

+0

А я вижу, что-то вроде' d [... ] 9: info_hash [длина]: [SHA hash] e' –

+1

Я боюсь, что нет. Как я уже упоминал в вопросительных комментариях, для самих файлов нет хеша SHA1, но для каждого небольшого фрагмента файла. Хэш-элементы полезны, потому что их можно проверить в начале процесса загрузки. Как только у вас будет одна действительная часть, вы можете поделиться ею с другими сверстниками ... Это говорит о том, что ваше решение md5 имеет то преимущество, что оно простое. Он просто не гарантированно доступен во всех файлах .torrent. –

16

Здесь как I'v е извлеченное значение HASH из торрента файла:

#!/usr/bin/python 

import sys, os, hashlib, StringIO 
import bencode 



def main(): 
    # Open torrent file 
    torrent_file = open(sys.argv[1], "rb") 
    metainfo = bencode.bdecode(torrent_file.read()) 
    info = metainfo['info'] 
    print hashlib.sha1(bencode.bencode(info)).hexdigest()  

if __name__ == "__main__": 
    main() 

Это то же самое, как работает команда:

transmissioncli -i test.torrent 2>/dev/null | grep "^hash:" | awk '{print $2}' 

Надежда, это помогает :)

+1

То, что дает вам, - это хэш-информация * торрента. –

+1

+1, так как это именно то, что я хотел сделать, когда я посетил вопрос о «извлечении хэша SHA1 из файла torrent». – sjy

+0

Хорошая небольшая часть кода, bencode не находится в Debian/Ubuntu dist, поэтому вам нужно _pip install_ it, или мне проще использовать модуль 'bzrlib.bencode' от _python-bzrlib_. – marcz