def create_v2_instances(self): instances = [] for i in range(0, self.num_instances): instance_key = Crypto.PublicKey.RSA.generate(1024) instance_address = util.calc_onion_address(instance_key) logger.debug("Created a key for instance %s.onion.", instance_address) instances.append((instance_address, instance_key)) return instances
def load_v2_master_key(self, master_key_path): if master_key_path: # Try load the specified private key file master_key = util.key_decrypt_prompt(master_key_path) if not master_key: logger.error("The specified master private key %s could not " "be loaded.", os.path.abspath(master_key)) sys.exit(1) master_onion_address = util.calc_onion_address(master_key) logger.info("Successfully loaded a master key for service " "%s.onion.", master_onion_address) else: # No key specified, begin generating a new one. master_key = Crypto.PublicKey.RSA.generate(1024) master_onion_address = util.calc_onion_address(master_key) logger.debug("Created a new master key for service %s.onion.", master_onion_address) return master_key, master_onion_address
def descriptor_received(descriptor_content): """ Process onion service descriptors retrieved from the HSDir system or received directly over the metadata channel. """ try: parsed_descriptor = stem.descriptor.hidden_service_descriptor.\ HiddenServiceDescriptor(descriptor_content, validate=True) except ValueError: logger.exception("Received an invalid service descriptor.") return None # Ensure the received descriptor matches the requested descriptor permanent_key = Crypto.PublicKey.RSA.importKey( parsed_descriptor.permanent_key) descriptor_onion_address = util.calc_onion_address(permanent_key) known_descriptor, instance_changed = False, False for instance in [ instance for service in config.services for instance in service.instances ]: if instance.onion_address == descriptor_onion_address: instance_changed |= instance.update_descriptor(parsed_descriptor) known_descriptor = True if instance_changed: logger.info( "The introduction point set has changed for instance " "%s.onion.", descriptor_onion_address) if not known_descriptor: # No matching service instance was found for the descriptor logger.debug("Received a descriptor for an unknown service:\n%s", descriptor_content.decode('utf-8')) logger.warning( "Received a descriptor with address %s.onion that " "did not match any configured service instances.", descriptor_onion_address) return None
def generate_service_descriptor(permanent_key, introduction_point_list=None, replica=0, timestamp=None, deviation=0): """ High-level interface for generating a signed HS descriptor """ if not timestamp: timestamp = datetime.datetime.utcnow() unix_timestamp = int(timestamp.strftime("%s")) permanent_key_block = make_public_key_block(permanent_key) permanent_id = util.calc_permanent_id(permanent_key) # Calculate the current secret-id-part for this hidden service # Deviation allows the generation of a descriptor for a different time # period. time_period = (util.get_time_period(unix_timestamp, permanent_id) + int(deviation)) secret_id_part = util.calc_secret_id_part(time_period, None, replica) descriptor_id = util.calc_descriptor_id(permanent_id, secret_id_part) if not introduction_point_list: onion_address = util.calc_onion_address(permanent_key) raise ValueError("No introduction points for service %s.onion." % onion_address) # Generate the introduction point section of the descriptor intro_section = make_introduction_points_part(introduction_point_list) unsigned_descriptor = generate_hs_descriptor_raw( desc_id_base32=util.base32_encode_str(descriptor_id), permanent_key_block=permanent_key_block, secret_id_part_base32=util.base32_encode_str(secret_id_part), publication_time=util.rounded_timestamp(timestamp), introduction_points_part=intro_section) signed_descriptor = sign_descriptor(unsigned_descriptor, permanent_key) return signed_descriptor
def __init__(self, controller, service_key=None, instances=None): """ Initialise a HiddenService object. """ self.controller = controller # Service key must be a valid PyCrypto RSA key object if isinstance(service_key, Crypto.PublicKey.RSA._RSAobj): self.service_key = service_key else: raise ValueError("Service key is not a valid RSA object.") # List of instances for this onion service if not instances: instances = [] self.instances = instances # Calculate the onion address for this service self.onion_address = util.calc_onion_address(self.service_key) # Timestamp when this descriptor was last attempted self.uploaded = None