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 test_blinding(self): """ Create a descriptor with key blinding. """ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey expected_blinded_key = b'\xb5\xefEA\xfaI\x1a\xd8*p\xcd\x97\x01\x90O\xa8p\xd3\x10\x16\x8e-\x19\xab+\x92\xbc\xf6\xe7\x92\xc2k' desc = HiddenServiceDescriptorV3.create( identity_key = Ed25519PrivateKey.from_private_bytes(b'a' * 32), blinding_nonce = b'a' * 32, ) self.assertEqual(64, len(desc.signing_cert.signature)) self.assertEqual(expected_blinded_key, desc.signing_cert.signing_key())
def __init__(self, onion_address, identity_priv_key, blinding_param, intro_points, is_first_desc): # Timestamp of the last attempt to assemble this descriptor self.last_publish_attempt_ts = None # Timestamp we last uploaded this descriptor self.last_upload_ts = None # Set of responsible HSDirs for last time we uploaded this descriptor self.responsible_hsdirs = None # Start generating descriptor desc_signing_key = Ed25519PrivateKey.generate() # Get the intro points for this descriptor and recertify them! recertified_intro_points = [] for ip in intro_points: recertified_intro_points.append( self._recertify_intro_point(ip, desc_signing_key)) rev_counter = self._get_revision_counter(identity_priv_key, is_first_desc) v3_desc_inner_layer = InnerLayer.create( introduction_points=recertified_intro_points) v3_desc = HiddenServiceDescriptorV3.create( blinding_nonce=blinding_param, identity_key=identity_priv_key, signing_key=desc_signing_key, inner_layer=v3_desc_inner_layer, revision_counter=int(rev_counter), ) # TODO stem should probably initialize it itself so that it has balance # between descriptor creation (where this is not inted) and descriptor # parsing (where this is inited) v3_desc._inner_layer = v3_desc_inner_layer # Check max size is within range if len(str(v3_desc)) > params.MAX_DESCRIPTOR_SIZE: logger.error( "Created descriptor is too big (%d intros). Consider " "relaxing number of instances or intro points per instance " "(see N_INTROS_PER_INSTANCE)") raise BadDescriptor super().__init__(onion_address, v3_desc)