def testSignOnion(self, tor_manager): address = tor_manager.addOnion() # Sign sign = CryptRsa.sign("hello", tor_manager.getPrivatekey(address)) assert len(sign) == 128 # Verify publickey = CryptRsa.privatekeyToPublickey(tor_manager.getPrivatekey(address)) assert len(publickey) == 140 assert CryptRsa.verify("hello", publickey, sign) assert not CryptRsa.verify("not hello", publickey, sign) # Pub to address assert CryptRsa.publickeyToOnion(publickey) == address # Delete tor_manager.delOnion(address)
def announceTracker(self, tracker_protocol, tracker_address, fileserver_port=0, add_types=[], my_peer_id="", mode="start"): if tracker_protocol != "zero": return super(SitePlugin, self).announceTracker( tracker_protocol, tracker_address, fileserver_port, add_types, my_peer_id, mode ) s = time.time() need_types = ["ip4"] if self.connection_server and self.connection_server.tor_manager and self.connection_server.tor_manager.enabled: need_types.append("onion") if mode == "start" or mode == "more": # Single: Announce only this site sites = [self] full_announce = False else: # Multi: Announce all currently serving site full_announce = True if time.time() - time_full_announced.get(tracker_address, 0) < 60 * 5: # No reannounce all sites within 5 minute return True time_full_announced[tracker_address] = time.time() from Site import SiteManager sites = [site for site in SiteManager.site_manager.sites.values() if site.settings["serving"]] # Create request request = { "hashes": [], "onions": [], "port": fileserver_port, "need_types": need_types, "need_num": 20, "add": add_types } for site in sites: if "onion" in add_types: onion = self.connection_server.tor_manager.getOnion(site.address) request["onions"].append(onion) request["hashes"].append(hashlib.sha256(site.address).digest()) # Tracker can remove sites that we don't announce if full_announce: request["delete"] = True # Sent request to tracker tracker = connection_pool.get(tracker_address) # Re-use tracker connection if possible if not tracker: tracker_ip, tracker_port = tracker_address.split(":") tracker = Peer(tracker_ip, tracker_port, connection_server=self.connection_server) connection_pool[tracker_address] = tracker res = tracker.request("announce", request) if not res or "peers" not in res: self.log.debug("Announce to %s failed: %s" % (tracker_address, res)) if full_announce: time_full_announced[tracker_address] = 0 return False # Add peers from response to site site_index = 0 for site_res in res["peers"]: site = sites[site_index] processPeerRes(site, site_res) site_index += 1 # Check if we need to sign prove the onion addresses if "onion_sign_this" in res: self.log.debug("Signing %s for %s to add %s onions" % (res["onion_sign_this"], tracker_address, len(sites))) request["onion_signs"] = {} request["onion_sign_this"] = res["onion_sign_this"] request["need_num"] = 0 for site in sites: onion = self.connection_server.tor_manager.getOnion(site.address) sign = CryptRsa.sign(res["onion_sign_this"], self.connection_server.tor_manager.getPrivatekey(onion)) request["onion_signs"][self.connection_server.tor_manager.getPublickey(onion)] = sign res = tracker.request("announce", request) if not res or "onion_sign_this" in res: self.log.debug("Announce onion address to %s failed: %s" % (tracker_address, res)) if full_announce: time_full_announced[tracker_address] = 0 return False if full_announce: tracker.remove() # Close connection, we don't need it in next 5 minute return time.time() - s
def announceTrackerZero(self, tracker_address, mode="start", num_want=10): global time_full_announced s = time.time() need_types = ["ip4"] if self.site.connection_server.tor_manager.enabled: need_types.append("onion") if mode == "start" or mode == "more": # Single: Announce only this site sites = [self.site] full_announce = False else: # Multi: Announce all currently serving site full_announce = True if time.time() - time_full_announced.get( tracker_address, 0) < 60 * 15: # No reannounce all sites within short time return None time_full_announced[tracker_address] = time.time() from Site import SiteManager sites = [ site for site in SiteManager.site_manager.sites.values() if site.settings["serving"] ] # Create request add_types = self.getOpenedServiceTypes() request = { "hashes": [], "onions": [], "port": self.fileserver_port, "need_types": need_types, "need_num": 20, "add": add_types } for site in sites: if "onion" in add_types: onion = self.site.connection_server.tor_manager.getOnion( site.address) request["onions"].append(onion) request["hashes"].append(site.address_hash) # Tracker can remove sites that we don't announce if full_announce: request["delete"] = True # Sent request to tracker tracker_peer = connection_pool.get( tracker_address) # Re-use tracker connection if possible if not tracker_peer: tracker_ip, tracker_port = tracker_address.split(":") tracker_peer = Peer(tracker_ip, tracker_port, connection_server=self.site.connection_server) tracker_peer.is_tracker_connection = True connection_pool[tracker_address] = tracker_peer res = tracker_peer.request("announce", request) if not res or "peers" not in res: if full_announce: time_full_announced[tracker_address] = 0 raise AnnounceError("Invalid response: %s" % res) # Add peers from response to site site_index = 0 peers_added = 0 for site_res in res["peers"]: site = sites[site_index] peers_added += processPeerRes(tracker_address, site, site_res) site_index += 1 # Check if we need to sign prove the onion addresses if "onion_sign_this" in res: self.site.log.debug( "Signing %s for %s to add %s onions" % (res["onion_sign_this"], tracker_address, len(sites))) request["onion_signs"] = {} request["onion_sign_this"] = res["onion_sign_this"] request["need_num"] = 0 for site in sites: onion = self.site.connection_server.tor_manager.getOnion( site.address) publickey = self.site.connection_server.tor_manager.getPublickey( onion) if publickey not in request["onion_signs"]: sign = CryptRsa.sign( res["onion_sign_this"], self.site.connection_server.tor_manager.getPrivatekey( onion)) request["onion_signs"][publickey] = sign res = tracker_peer.request("announce", request) if not res or "onion_sign_this" in res: if full_announce: time_full_announced[tracker_address] = 0 raise AnnounceError("Announce onion address to failed: %s" % res) if full_announce: tracker_peer.remove( ) # Close connection, we don't need it in next 5 minute self.site.log.debug( "Tracker announce result: zero://%s (sites: %s, new peers: %s) in %.3fs" % (tracker_address, site_index, peers_added, time.time() - s)) return True
def testAddOnion(self, file_server, site, bootstrapper_db, tor_manager): onion1 = tor_manager.addOnion() onion2 = tor_manager.addOnion() peer = Peer("127.0.0.1", 1544, connection_server=file_server) hash1 = hashlib.sha256("site1").digest() hash2 = hashlib.sha256("site2").digest() hash3 = hashlib.sha256("site3").digest() bootstrapper_db.peerAnnounce(ip4="1.2.3.4", port=1234, hashes=[hash1, hash2, hash3]) res = peer.request( "announce", { "onions": [onion1, onion1, onion2], "hashes": [hash1, hash2, hash3], "port": 15441, "need_types": ["ip4", "onion"], "need_num": 10, "add": ["onion"] }) assert len(res["peers"][0]["ip4"]) == 1 # Onion address not added yet site_peers = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash1) assert len(site_peers["onion"]) == 0 assert "onion_sign_this" in res # Sign the nonces sign1 = CryptRsa.sign(res["onion_sign_this"], tor_manager.getPrivatekey(onion1)) sign2 = CryptRsa.sign(res["onion_sign_this"], tor_manager.getPrivatekey(onion2)) # Bad sign (different address) res = peer.request( "announce", { "onions": [onion1], "onion_sign_this": res["onion_sign_this"], "onion_signs": { tor_manager.getPublickey(onion2): sign2 }, "hashes": [hash1], "port": 15441, "need_types": ["ip4", "onion"], "need_num": 10, "add": ["onion"] }) assert "onion_sign_this" in res site_peers1 = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash1) assert len(site_peers1["onion"]) == 0 # Not added # Bad sign (missing one) res = peer.request( "announce", { "onions": [onion1, onion1, onion2], "onion_sign_this": res["onion_sign_this"], "onion_signs": { tor_manager.getPublickey(onion1): sign1 }, "hashes": [hash1, hash2, hash3], "port": 15441, "need_types": ["ip4", "onion"], "need_num": 10, "add": ["onion"] }) assert "onion_sign_this" in res site_peers1 = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash1) assert len(site_peers1["onion"]) == 0 # Not added # Good sign res = peer.request( "announce", { "onions": [onion1, onion1, onion2], "onion_sign_this": res["onion_sign_this"], "onion_signs": { tor_manager.getPublickey(onion1): sign1, tor_manager.getPublickey(onion2): sign2 }, "hashes": [hash1, hash2, hash3], "port": 15441, "need_types": ["ip4", "onion"], "need_num": 10, "add": ["onion"] }) assert "onion_sign_this" not in res # Onion addresses added site_peers1 = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash1) assert len(site_peers1["onion"]) == 1 site_peers2 = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash2) assert len(site_peers2["onion"]) == 1 site_peers3 = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash3) assert len(site_peers3["onion"]) == 1 assert site_peers1["onion"][0] == site_peers2["onion"][0] assert site_peers2["onion"][0] != site_peers3["onion"][0] assert helper.unpackOnionAddress( site_peers1["onion"][0])[0] == onion1 + ".onion" assert helper.unpackOnionAddress( site_peers2["onion"][0])[0] == onion1 + ".onion" assert helper.unpackOnionAddress( site_peers3["onion"][0])[0] == onion2 + ".onion" tor_manager.delOnion(onion1) tor_manager.delOnion(onion2)
def testAddOnion(self, file_server, site, bootstrapper_db, tor_manager): onion1 = tor_manager.addOnion() onion2 = tor_manager.addOnion() peer = Peer("127.0.0.1", 1544, connection_server=file_server) hash1 = hashlib.sha256("site1").digest() hash2 = hashlib.sha256("site2").digest() bootstrapper_db.peerAnnounce(ip4="1.2.3.4", port=1234, hashes=[hash1, hash2]) res = peer.request("announce", { "onions": [onion1, onion2], "hashes": [hash1, hash2], "port": 15441, "need_types": ["ip4", "onion"], "need_num": 10, "add": ["onion"] }) assert len(res["peers"][0]["ip4"]) == 1 assert "onion_sign_this" in res # Onion address not added yet site_peers = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash1) assert len(site_peers["onion"]) == 0 assert "onion_sign_this" in res # Sign the nonces sign1 = CryptRsa.sign(res["onion_sign_this"], tor_manager.getPrivatekey(onion1)) sign2 = CryptRsa.sign(res["onion_sign_this"], tor_manager.getPrivatekey(onion2)) # Bad sign (different address) res = peer.request("announce", { "onions": [onion1], "onion_sign_this": res["onion_sign_this"], "onion_signs": {tor_manager.getPublickey(onion2): sign2}, "hashes": [hash1], "port": 15441, "need_types": ["ip4", "onion"], "need_num": 10, "add": ["onion"] }) assert "onion_sign_this" in res site_peers1 = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash1) assert len(site_peers1["onion"]) == 0 # Not added # Bad sign (missing one) res = peer.request("announce", { "onions": [onion1, onion2], "onion_sign_this": res["onion_sign_this"], "onion_signs": {tor_manager.getPublickey(onion1): sign1}, "hashes": [hash1, hash2], "port": 15441, "need_types": ["ip4", "onion"], "need_num": 10, "add": ["onion"] }) assert "onion_sign_this" in res site_peers1 = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash1) assert len(site_peers1["onion"]) == 0 # Not added # Good sign res = peer.request("announce", { "onions": [onion1, onion2], "onion_sign_this": res["onion_sign_this"], "onion_signs": {tor_manager.getPublickey(onion1): sign1, tor_manager.getPublickey(onion2): sign2}, "hashes": [hash1, hash2], "port": 15441, "need_types": ["ip4", "onion"], "need_num": 10, "add": ["onion"] }) assert "onion_sign_this" not in res # Onion addresses added site_peers1 = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash1) assert len(site_peers1["onion"]) == 1 site_peers2 = bootstrapper_db.peerList(ip4="1.2.3.4", port=1234, hash=hash2) assert len(site_peers2["onion"]) == 1 assert site_peers1["onion"][0] != site_peers2["onion"][0] assert helper.unpackOnionAddress(site_peers1["onion"][0])[0] == onion1+".onion" assert helper.unpackOnionAddress(site_peers2["onion"][0])[0] == onion2+".onion" tor_manager.delOnion(onion1) tor_manager.delOnion(onion2)
def announceTrackerZero(self, tracker_address, mode="start", num_want=10): global time_full_announced s = time.time() need_types = ["ip4"] if self.site.connection_server.tor_manager.enabled: need_types.append("onion") if mode == "start" or mode == "more": # Single: Announce only this site sites = [self.site] full_announce = False else: # Multi: Announce all currently serving site full_announce = True if time.time() - time_full_announced.get(tracker_address, 0) < 60 * 5: # No reannounce all sites within 5 minute return [] time_full_announced[tracker_address] = time.time() from Site import SiteManager sites = [site for site in SiteManager.site_manager.sites.values() if site.settings["serving"]] # Create request add_types = self.getOpenedServiceTypes() request = { "hashes": [], "onions": [], "port": self.fileserver_port, "need_types": need_types, "need_num": 20, "add": add_types } for site in sites: if "onion" in add_types: onion = self.site.connection_server.tor_manager.getOnion(site.address) request["onions"].append(onion) request["hashes"].append(site.address_hash) # Tracker can remove sites that we don't announce if full_announce: request["delete"] = True # Sent request to tracker tracker = connection_pool.get(tracker_address) # Re-use tracker connection if possible if not tracker: tracker_ip, tracker_port = tracker_address.split(":") tracker = Peer(tracker_ip, tracker_port, connection_server=self.site.connection_server) connection_pool[tracker_address] = tracker res = tracker.request("announce", request) if not res or "peers" not in res: if full_announce: time_full_announced[tracker_address] = 0 raise AnnounceError("Invalid response: %s" % res) # Add peers from response to site site_index = 0 peers_added = 0 for site_res in res["peers"]: site = sites[site_index] peers_added += processPeerRes(tracker_address, site, site_res) site_index += 1 # Check if we need to sign prove the onion addresses if "onion_sign_this" in res: self.site.log.debug("Signing %s for %s to add %s onions" % (res["onion_sign_this"], tracker_address, len(sites))) request["onion_signs"] = {} request["onion_sign_this"] = res["onion_sign_this"] request["need_num"] = 0 for site in sites: onion = self.site.connection_server.tor_manager.getOnion(site.address) publickey = self.site.connection_server.tor_manager.getPublickey(onion) if publickey not in request["onion_signs"]: sign = CryptRsa.sign(res["onion_sign_this"], self.site.connection_server.tor_manager.getPrivatekey(onion)) request["onion_signs"][publickey] = sign res = tracker.request("announce", request) if not res or "onion_sign_this" in res: if full_announce: time_full_announced[tracker_address] = 0 raise AnnounceError("Announce onion address to failed: %s" % res) if full_announce: tracker.remove() # Close connection, we don't need it in next 5 minute self.site.log.debug( "Tracker announce result: zero://%s (sites: %s, new peers: %s) in %.3fs" % (tracker_address, site_index, peers_added, time.time() - s) ) return None