From 7d07c2ed0750e4a927c5a0485d8b8fbb8dda25b2 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Tue, 6 Jun 2017 15:11:42 -0400 Subject: [PATCH 1/2] util.config.validators: fix torrent validation This code was mistaken the info dict with the params passed in an announce request. Rather, now we expose a function for creating a jwt from infohashes directly. --- util/config/validators/validate_torrent.py | 6 ++--- util/registry/torrent.py | 27 ++++++++++++++-------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/util/config/validators/validate_torrent.py b/util/config/validators/validate_torrent.py index 2cfc376b6..30d53d897 100644 --- a/util/config/validators/validate_torrent.py +++ b/util/config/validators/validate_torrent.py @@ -4,7 +4,7 @@ from hashlib import sha1 from app import app from util.config.validators import BaseValidator, ConfigValidationException -from util.registry.torrent import torrent_jwt +from util.registry.torrent import jwt_from_infohash logger = logging.getLogger(__name__) @@ -22,7 +22,7 @@ class BittorrentValidator(BaseValidator): client = app.config['HTTPCLIENT'] params = { - 'info_hash': sha1('somedata').digest(), + 'info_hash': sha1('test').digest(), 'peer_id': '-QUAY00-6wfG2wk6wWLc', 'uploaded': 0, 'downloaded': 0, @@ -31,7 +31,7 @@ class BittorrentValidator(BaseValidator): 'port': 80, } - encoded_jwt = torrent_jwt(params) + encoded_jwt = jwt_from_infohash(params['info_hash']) params['jwt'] = encoded_jwt resp = client.get(announce_url, timeout=5, params=params) diff --git a/util/registry/torrent.py b/util/registry/torrent.py index 74db8dd70..e0c618bf9 100644 --- a/util/registry/torrent.py +++ b/util/registry/torrent.py @@ -1,7 +1,7 @@ import hashlib import time -import urllib +from binascii import hexlify from cachetools import lru_cache import bencode @@ -21,22 +21,27 @@ def _load_private_key(private_key_file_path): with open(private_key_file_path) as private_key_file: return private_key_file.read() -def torrent_jwt(info_dict): - """ Returns an encoded JWT for the given information dictionary, signed by the local instance's + +def jwt_from_infodict(infodict): + """ Returns an encoded JWT for the given BitTorrent info dict, signed by the local instance's + private key. + """ + digest = hashlib.sha1() + digest.update(bencode.bencode(infodict)) + return jwt_from_infohash(digest.digest()) + + +def jwt_from_infohash(infohash_digest): + """ Returns an encoded JWT for the given BitTorrent infohash, signed by the local instance's private key. """ token_data = { 'iss': instance_keys.service_name, 'aud': ANNOUNCE_URL, - 'infohash': _infohash(info_dict), + 'infohash': hexlify(infohash_digest), } - return jwt.encode(token_data, instance_keys.local_private_key, 'RS256') -def _infohash(infodict): - digest = hashlib.sha1() - digest.update(bencode.bencode(infodict)) - return urllib.quote(digest.digest()) def make_torrent(name, webseed, length, piece_length, pieces): info_dict = { @@ -48,7 +53,7 @@ def make_torrent(name, webseed, length, piece_length, pieces): } return bencode.bencode({ - 'announce': ANNOUNCE_URL + "?jwt=" + torrent_jwt(info_dict), + 'announce': ANNOUNCE_URL + "?jwt=" + jwt_from_infodict(info_dict), 'url-list': webseed, 'encoding': 'UTF-8', 'created by': REGISTRY_TITLE, @@ -56,9 +61,11 @@ def make_torrent(name, webseed, length, piece_length, pieces): 'info': info_dict, }) + def public_torrent_filename(blob_uuid): return hashlib.sha256(blob_uuid).hexdigest() + def per_user_torrent_filename(user_uuid, blob_uuid): return hashlib.sha256(FILENAME_PEPPER + "||" + blob_uuid + "||" + user_uuid).hexdigest() From a16b469d9b858a4842987032b636234022571ea1 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Thu, 8 Jun 2017 13:51:13 -0400 Subject: [PATCH 2/2] util.registry.torrent: stash kid in JWT headers Upstream, chihaya reads this header in order to find the kid in the list of maintained keys. A long time ago, it used to just iterate, but now it needs to know the kid. --- util/registry/torrent.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/registry/torrent.py b/util/registry/torrent.py index e0c618bf9..90f053d4c 100644 --- a/util/registry/torrent.py +++ b/util/registry/torrent.py @@ -40,7 +40,8 @@ def jwt_from_infohash(infohash_digest): 'aud': ANNOUNCE_URL, 'infohash': hexlify(infohash_digest), } - return jwt.encode(token_data, instance_keys.local_private_key, 'RS256') + return jwt.encode(token_data, instance_keys.local_private_key, algorithm='RS256', + headers={'kid': instance_keys.local_key_id}) def make_torrent(name, webseed, length, piece_length, pieces):