2010-04-03 36 views
21

He echado un vistazo para encontrar la respuesta, pero parece que solo puedo encontrar el software que lo haga por usted. ¿Alguien sabe cómo hacer esto en Python?Extraiga el hash SHA1 de un archivo torrent

+5

un torrente archivo almacena la del SHA1 de cada uno * piezas * de los archivos compartidos y un SHA1 de los metadatos del torrente * (el hash metainfo) *. ¿Qué hash quieres exactamente? –

+0

Sería el hash de cada una de las piezas. ¿El archivo no contiene un hash para que el archivo completo compruebe si hay errores? –

+2

Algunos archivos .torrent incluyen un hash md5 de cada archivo, pero eso es una extensión opcional del formato de archivo. El hash de piezas se puede usar para verificar la validez de los archivos, por supuesto. Simplemente verifica si todas las piezas están allí y si todas tienen el hash correcto. –

Respuesta

27

me escribió una pieza de código Python que verifica los valores hash de los archivos descargados contra de lo que hay en un archivo .torrent . Suponiendo que desea verificar una descarga por corrupción, puede resultar útil.

Necesita el bencode package para usar esto. Bencode es el formato de serialización utilizado en los archivos .torrent. Puede ordenar listas, diccionarios, cadenas y números como JSON.

El código toma los valores hash contenidos en la cadena info['pieces']:

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

Esa cadena contiene una sucesión de 20 bytes hash (una para cada pieza). Estos hashes se comparan con el hash de las piezas de archivo (s) en disco.

La única parte complicada de este código es el manejo de los torrentes de varios archivos debido a que un solo torrente pieza puede abarcar más de un archivo (internamente BitTorrent trata descargas de varios archivos en un único archivo contiguo). Estoy usando la función del generador pieces_generator() para abstraer eso.

Es posible que desee leer el BitTorrent spec para comprender esto en más detalles.

código completo abajo:

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

No sé si esto resolvió el problema del OP, pero definitivamente resolvió el mío (una vez superado el incumplimiento del paquete bencode: http://stackoverflow.com/questions/2693963/importing-bittorrent-bencode-module). ¡Gracias! –

+0

Siempre quise tener una herramienta así, y estaba a punto de profundizar en el viejo cliente oficial de python para descubrir cómo escribir una. ¡¡Gracias!! – netvope

-2

Según this, usted debería ser capaz de encontrar las md5sums de archivos mediante la búsqueda de la parte de los datos que se parece a:

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

(SHA no es parte de la especificación)

+1

Simplemente busque SHA en la página que ha vinculado y verá que se usa extensamente. También cite: 'md5sum: (opcional) un hex de 32 caracteres [...] BitTorrent no lo usa en absoluto, pero está incluido en algunos programas' –

+0

Ah, ya veo, algo así como' d ... ] 9: info_hash [longitud]: [SHA hash] e' –

+1

Me temo que no. Como mencioné en los comentarios de la pregunta, no hay ningún hash SHA1 para los archivos en sí, sino para cada pequeño fragmento de archivo. Los hash de piezas son útiles porque se pueden verificar al principio del proceso de descarga. Tan pronto como tenga una pieza válida, podrá compartirla con otros pares ... Dicho esto, su solución md5 tiene la ventaja de ser simple. Simplemente no está garantizado que esté disponible en todos los archivos .torrent. –

16

Aquí cómo I'v e extraída valor hash del archivo torrent:

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

Es el mismo que el comando se ejecuta:

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

Esperanza, que ayuda :)

+1

Lo que eso te da es la * info hash * del torrent. –

+1

+1 ya que eso es exactamente lo que quería hacer cuando visité una pregunta sobre "extraer el hash SHA1 de un archivo torrent". – sjy

+0

Buena pieza pequeña de código, bencode no está en Debian/Ubuntu dist, por lo que tiene que \pip install_ it, o me resulta más fácil utilizar el módulo 'bzrlib.bencode' de _python-bzrlib_. – marcz

Cuestiones relacionadas