2010-04-03 13 views
21

Szukałem odpowiedzi na to pytanie, ale wydaje mi się, że mogę znaleźć oprogramowanie, które zrobi to za Ciebie. Czy ktoś wie, jak to zrobić w python?Wyodrębnij hash SHA1 z pliku torrentowego

+5

potok plików przechowuje SHA1 każdego sztuk * * udostępnionych plików i SHA1 metadanych torrenta * (hash metainfo) *. Którą mieszankę chcesz dokładnie? –

+0

Byłby haszyszem dla każdego kawałka. Czy plik nie zawiera również skrótu do ukończonego pliku, aby sprawdzić błędy? –

+2

Niektóre pliki .torrent zawierają skróty md5 każdego pliku, ale jest to opcjonalne rozszerzenie formatu pliku. Hash elementów może być oczywiście użyty do sprawdzenia poprawności plików. Po prostu sprawdź, czy wszystkie elementy są tam i czy wszystkie mają właściwe hash. –

Odpowiedz

27

Napisałem kawałek kodu Pythona, który weryfikuje skrótów z pobranych plików przeciwko temu, co znajduje się w pliku .torrent. Zakładając, że chcesz sprawdzić pobieranie za korupcję, możesz uznać to za przydatne.

Do korzystania z tej funkcji potrzebny jest bencode package. Bencode to format serializacji używany w plikach .torrent. Może marszałczyć listy, słowniki, łańcuchy i liczby podobne do JSON.

kod ten mieszań zawartych w ciągu info['pieces']:

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

to ciąg zawiera serii 20 mieszań bajtów (jedno dla każdego elementu). Te skróty są następnie porównywane z hashem fragmentów pliku na dysku.

Jedynym skomplikowana część tego kodu jest obsługa torrentów wielu plików, ponieważ jeden torrent kawałek może obejmować więcej niż jeden plik (wewnętrznie BitTorrent traktuje pobieranie wielu plików w jeden ciągły plik). Używam funkcji generatora pieces_generator(), aby ją wykreślić.

Możesz przeczytać BitTorrent spec, aby zrozumieć to bardziej szczegółowo.

Pełny kod poniżej:

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

Nie wiem, czy to rozwiązało problem OP, ale zdecydowanie rozwiązało moje (gdy minęło złamanie pakietu bencode: http://stackoverflow.com/questions/2693963/importing-bittorrent-bencode-module). Dzięki! –

+0

Zawsze chciałem mieć takie narzędzie i miałem zamiar zagłębić się w starego oficjalnego klienta Pythona, aby dowiedzieć się, jak go napisać. Dzięki!! – netvope

-2

Według this, powinieneś być w stanie znaleźć sumy kontrolne MD5 plików wyszukując części danych, które wygląda następująco:

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

(SHA nie jest częścią specyfikacji)

+1

Po prostu wyszukaj SHA na stronie, którą połączyłeś, a zobaczysz, że jest szeroko używana. Zacytuj także: 'md5sum: (opcjonalnie) 32-znakowy hex [...] To nie jest w ogóle używane przez BitTorrenta, ale jest włączone przez niektóre programy' –

+0

Ah Widzę, więc coś jak 'd [... ] 9: info_hash [długość]: [SHA hash] e'' –

+1

Obawiam się, że nie. Jak wspomniałem w komentarzach do pytań, nie ma skrótu SHA1 dla samych plików, ale dla każdego małego fragmentu pliku. Skrót Kawałki jest przydatny, ponieważ można go zweryfikować na wczesnym etapie procesu pobierania. Jak tylko masz jeden ważny kawałek, możesz podzielić się nim z innymi rówieśnikami ... To oznacza, że ​​twoje rozwiązanie md5 ma tę zaletę, że jest proste. Nie można zagwarantować, że będzie on dostępny we wszystkich plikach .torrent. –

16

Oto jak ja e ekstrakcji wartość skrótu z torrentami pliku:

#!/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() 

To jest taka sama jak działa polecenia:

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

Hope, to pomaga :)

+1

To, co ci daje, to hash * informacji o potoku. –

+1

+1, ponieważ jest to dokładnie to, co chciałem zrobić, gdy odwiedziłem pytanie o "wyodrębnianie hasha SHA1 z pliku torrent". – sjy

+0

Miły mały kawałek kodu, bencode nie jest w dystrybucji Debian/Ubuntu, więc musisz _pip install_ it, albo łatwiej znaleźć moduł 'bzrlib.bencode' z _python-bzrlib_. – marcz