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
Odpowiedz
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()
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! –
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
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)
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' –
Ah Widzę, więc coś jak 'd [... ] 9: info_hash [długość]: [SHA hash] e'' –
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. –
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 :)
To, co ci daje, to hash * informacji o potoku. –
+1, ponieważ jest to dokładnie to, co chciałem zrobić, gdy odwiedziłem pytanie o "wyodrębnianie hasha SHA1 z pliku torrent". – sjy
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
potok plików przechowuje SHA1 każdego sztuk * * udostępnionych plików i SHA1 metadanych torrenta * (hash metainfo) *. Którą mieszankę chcesz dokładnie? –
Byłby haszyszem dla każdego kawałka. Czy plik nie zawiera również skrótu do ukończonego pliku, aby sprawdzić błędy? –
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. –