commit eea41c17ed53ab44552f6b2c3fc574bc3710fb82 Author: Damian Johnson atagar@torproject.org Date: Fri Nov 22 14:18:07 2019 -0800
More flexible IntroductionPointV3 construction
Renaming our IntroductionPointV3's create() method to create_from_address, and adding create_for_link_specifiers(). If other constructors are useful we can add using a similar convention. --- stem/descriptor/hidden_service.py | 28 +++++++++++++++++++++++++--- test/unit/descriptor/hidden_service_v3.py | 18 +++++++++--------- 2 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/stem/descriptor/hidden_service.py b/stem/descriptor/hidden_service.py index 983fb94b..13fae6ba 100644 --- a/stem/descriptor/hidden_service.py +++ b/stem/descriptor/hidden_service.py @@ -207,10 +207,9 @@ class IntroductionPointV3(collections.namedtuple('IntroductionPointV3', ['link_s return IntroductionPointV3(link_specifiers, onion_key, auth_key_cert, enc_key, enc_key_cert, legacy_key, legacy_key_cert)
@staticmethod - def create(address, port, expiration = None, onion_key = None, enc_key = None, auth_key = None, signing_key = None): + def create_for_address(address, port, expiration = None, onion_key = None, enc_key = None, auth_key = None, signing_key = None): """ - Simplified constructor. For more sophisticated use cases you can use this - as a template for how introduction points are properly created. + Simplified constructor for a single address/port link specifier.
:param str address: IPv4 or IPv6 address where the service is reachable :param int port: port where the service is reachable @@ -237,6 +236,29 @@ class IntroductionPointV3(collections.namedtuple('IntroductionPointV3', ['link_s else: raise ValueError("'%s' is not a valid IPv4 or IPv6 address" % address)
+ return IntroductionPointV3.create_for_link_specifiers(link_specifiers, expiration = None, onion_key = None, enc_key = None, auth_key = None, signing_key = None) + + @staticmethod + def create_for_link_specifiers(link_specifiers, expiration = None, onion_key = None, enc_key = None, auth_key = None, signing_key = None): + """ + Simplified constructor. For more sophisticated use cases you can use this + as a template for how introduction points are properly created. + + :param list link_specifiers: series of stem.client.datatype.LinkSpecifier where the service is reachable + :param datetime.datetime expiration: when certificates should expire + :param str onion_key: encoded, X25519PublicKey, or X25519PrivateKey onion key + :param str enc_key: encoded, X25519PublicKey, or X25519PrivateKey encryption key + :param str auth_key: encoded, Ed25519PublicKey, or Ed25519PrivateKey authentication key + :param cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey signing_key: service signing key + + :returns: :class:`~stem.descriptor.hidden_service.IntroductionPointV3` with these attributes + + :raises: **ValueError** if the address, port, or keys are malformed + """ + + if not stem.prereq.is_crypto_available(ed25519 = True): + raise ImportError('Introduction point creation requires the cryptography module ed25519 support') + from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
diff --git a/test/unit/descriptor/hidden_service_v3.py b/test/unit/descriptor/hidden_service_v3.py index cb1e9c68..180493c1 100644 --- a/test/unit/descriptor/hidden_service_v3.py +++ b/test/unit/descriptor/hidden_service_v3.py @@ -300,7 +300,7 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase): Create an introduction point, encode it, then re-parse. """
- intro_point = IntroductionPointV3.create('1.1.1.1', 9001) + intro_point = IntroductionPointV3.create_for_address('1.1.1.1', 9001)
self.assertEqual(1, len(intro_point.link_specifiers)) self.assertEqual(stem.client.datatype.LinkByIPv4, type(intro_point.link_specifiers[0])) @@ -341,16 +341,16 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase): # include introduction points
desc = InnerLayer.create(introduction_points = [ - IntroductionPointV3.create('1.1.1.1', 9001), - IntroductionPointV3.create('2.2.2.2', 9001), - IntroductionPointV3.create('3.3.3.3', 9001), + 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), ])
self.assertEqual(3, len(desc.introduction_points)) self.assertEqual('1.1.1.1', desc.introduction_points[0].link_specifiers[0].address)
self.assertTrue(InnerLayer.content(introduction_points = [ - IntroductionPointV3.create('1.1.1.1', 9001), + IntroductionPointV3.create_for_address('1.1.1.1', 9001), ]).startswith(b'create2-formats 2\nintroduction-point AQAGAQEBASMp'))
@test.require.ed25519_support @@ -398,7 +398,7 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase): outer_layer = OuterLayer.create( inner_layer = InnerLayer.create( introduction_points = [ - IntroductionPointV3.create('1.1.1.1', 9001), + IntroductionPointV3.create_for_address('1.1.1.1', 9001), ] ), revision_counter = revision_counter, @@ -450,9 +450,9 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase): desc = HiddenServiceDescriptorV3.create( identity_key = identity_key, inner_layer = InnerLayer.create(introduction_points = [ - IntroductionPointV3.create('1.1.1.1', 9001), - IntroductionPointV3.create('2.2.2.2', 9001), - IntroductionPointV3.create('3.3.3.3', 9001), + 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), ]), )