def _load_v3_master_key_from_file(self, master_key_path): """ Load a private key straight from a Tor instance (no OBv3 keys supported) and return the private key and onion address. """ try: with open(master_key_path, 'rb') as handle: pem_key_bytes = handle.read() except EnvironmentError as e: logger.error("Unable to read service private key file ('%s')", e) sys.exit(1) try: master_private_key = tor_ed25519.load_tor_key_from_disk(pem_key_bytes) except ValueError: logger.error("Please provide path to a valid Tor master key") sys.exit(1) identity_pub_key = master_private_key.public_key() identity_pub_key_bytes = identity_pub_key.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) master_onion_address = HiddenServiceDescriptorV3.address_from_identity_key(identity_pub_key_bytes) # remove the trailing .onion master_onion_address = master_onion_address.replace(".onion", "") self.v3_loaded_key_from_file = True return master_private_key, master_onion_address
def test_descriptor_creation(self): """ HiddenServiceDescriptorV3 creation. """ # minimal descriptor self.assertTrue(HiddenServiceDescriptorV3.content().startswith( b'hs-descriptor 3\ndescriptor-lifetime 180\n')) self.assertEqual(180, HiddenServiceDescriptorV3.create().lifetime) # specify the parameters desc = HiddenServiceDescriptorV3.create( { 'hs-descriptor': '4', 'descriptor-lifetime': '123', 'descriptor-signing-key-cert': '\n-----BEGIN ED25519 CERT-----\nmalformed block\n-----END ED25519 CERT-----', 'revision-counter': '5', 'superencrypted': '\n-----BEGIN MESSAGE-----\nmalformed block\n-----END MESSAGE-----', 'signature': 'abcde', }, validate=False) self.assertEqual(4, desc.version) self.assertEqual(123, desc.lifetime) self.assertEqual( None, desc.signing_cert ) # malformed cert dropped because validation is disabled self.assertEqual(5, desc.revision_counter) self.assertEqual( '-----BEGIN MESSAGE-----\nmalformed block\n-----END MESSAGE-----', desc.superencrypted) self.assertEqual('abcde', desc.signature) # include introduction points from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey identity_key = Ed25519PrivateKey.generate() onion_address = HiddenServiceDescriptorV3.address_from_identity_key( identity_key) desc = HiddenServiceDescriptorV3.create( identity_key=identity_key, inner_layer=InnerLayer.create(introduction_points=[ IntroductionPointV3.create_for_address('1.1.1.1', 9001), IntroductionPointV3.create_for_address('2.2.2.2', 9001), IntroductionPointV3.create_for_address('3.3.3.3', 9001), ]), ) inner_layer = desc.decrypt(onion_address) self.assertEqual(3, len(inner_layer.introduction_points)) self.assertEqual( '1.1.1.1', inner_layer.introduction_points[0].link_specifiers[0].address)
def load_v3_master_key(self, master_key_path): if master_key_path: # load key from file return self._load_v3_master_key_from_file(master_key_path) else: # generate new v3 key master_private_key = Ed25519PrivateKey.generate() master_public_key = master_private_key.public_key() master_pub_key_bytes = master_public_key.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) master_onion_address = HiddenServiceDescriptorV3.address_from_identity_key(master_pub_key_bytes) # cut out the onion since that's what the rest of the code expects master_onion_address = master_onion_address.replace(".onion", "") return master_private_key, master_onion_address
def _load_service_keys(self, service_config_data, config_path): # First of all let's load up the private key key_fname = service_config_data['key'] config_directory = os.path.dirname(config_path) if not os.path.isabs(key_fname): key_fname = os.path.join(config_directory, key_fname) try: with open(key_fname, 'rb') as handle: pem_key_bytes = handle.read() except EnvironmentError as e: logger.critical("Unable to read service private key file ('%s')", e) raise BadServiceInit # Get the service private key # First try with the OBv3 PEM format identity_priv_key = None try: identity_priv_key = serialization.load_pem_private_key( pem_key_bytes, password=None, backend=default_backend()) except ValueError as e: logger.warning( "Service private key not in OBv3 format ('%s'). Trying tor's format...", e) # If the key was not in OBv3 PEM format, try the Tor binary format if not identity_priv_key: try: identity_priv_key = tor_ed25519.load_tor_key_from_disk( pem_key_bytes) self.is_priv_key_in_tor_format = True except ValueError as e: logger.warning( "Service private key not in Tor format either ('%s'). Aborting.", e) raise BadServiceInit # Get onion address identity_pub_key = identity_priv_key.public_key() identity_pub_key_bytes = identity_pub_key.public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) onion_address = HiddenServiceDescriptorV3.address_from_identity_key( identity_pub_key_bytes) logger.warning("Loaded onion %s from %s", onion_address, key_fname) return identity_priv_key, onion_address
def _load_service_keys(self, service_config_data, config_path): # First of all let's load up the private key key_fname = service_config_data['key'] config_directory = os.path.dirname(config_path) if not os.path.isabs(key_fname): key_fname = os.path.join(config_directory, key_fname) with open(key_fname, 'rb') as handle: pem_key_bytes = handle.read() identity_priv_key = serialization.load_pem_private_key( pem_key_bytes, password=None, backend=default_backend()) # Get onion address identity_pub_key = identity_priv_key.public_key() identity_pub_key_bytes = identity_pub_key.public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) onion_address = HiddenServiceDescriptorV3.address_from_identity_key( identity_pub_key_bytes) logger.warning("Loaded onion %s from %s", onion_address, key_fname) return identity_priv_key, onion_address
def test_address_from_identity_key(self): self.assertEqual(HS_ADDRESS, HiddenServiceDescriptorV3.address_from_identity_key(HS_PUBKEY))