commit ba8cee36a0348c1509ad3562051723b7948e19ce Author: Damian Johnson atagar@torproject.org Date: Fri May 29 08:45:30 2015 -0700
'extra-info-digest line had an invalid value' from additions in proposal 228
Proposal 228 adds additional content to the extra-info-digest line of server descriptors, causing validation to fail with...
ValueError: extra-info-digest line had an invalid value (should be 40 hex characters): extra-info-digest 0879DB7B765218D7B3AE7557669D20307BB21CAA V609l+N6ActBveebfNbH5lQ6wHDNstDkFgyqEhBHwtA
Honestly Stem is probably being a bit too strict here. Following is tracking spec clarifications...
https://trac.torproject.org/projects/tor/ticket/16227
And as for proposal 228 itself awaiting its dir-spec addition...
https://trac.torproject.org/projects/tor/ticket/16235 --- docs/change_log.rst | 4 ++ stem/descriptor/server_descriptor.py | 11 ++++- .../descriptor/data/server_descriptor_with_ed25519 | 50 ++++++++++++++++++++ test/unit/descriptor/server_descriptor.py | 39 +++++++++++++++ 4 files changed, 103 insertions(+), 1 deletion(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst index 643f5bd..aea62a2 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -49,6 +49,10 @@ The following are only available within Stem's `git repository * Added `support for NETWORK_LIVENESS events <api/response.html#stem.response.events.NetworkLivenessEvent>`_ (:spec:`44aac63`) * IPv6 addresses could trigger errors in :func:`~stem.control.Controller.get_listeners`, :class:`~stem.response.events.ORConnEvent`, and quite a few other things (:trac:`16174`)
+ * **Descriptors** + + * Server descriptor validation fails with 'extra-info-digest line had an invalid value' from additions in proposal 228 (:trac:`16227`) + * **Website**
* Example for `custom path selection for circuits <tutorials/to_russia_with_love.html#custom-path-selection>`_ (:trac:`8728`) diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py index b375066..22e6f40 100644 --- a/stem/descriptor/server_descriptor.py +++ b/stem/descriptor/server_descriptor.py @@ -265,6 +265,16 @@ def _parse_fingerprint_line(descriptor, entries): descriptor.fingerprint = fingerprint
+def _parse_extrainfo_digest_line(descriptor, entries): + value = _value('extra-info-digest', entries) + value = value.split(' ')[0] # lines have additional content from propsal 228, waiting for it to be documented: #16227 + + if not stem.util.tor_tools.is_hex_digits(value, 40): + raise ValueError('extra-info-digest should be 40 hex characters: %s' % value) + + descriptor.extra_info_digest = value + + def _parse_hibernating_line(descriptor, entries): # "hibernating" 0|1 (in practice only set if one)
@@ -374,7 +384,6 @@ def _parse_exit_policy(descriptor, entries):
_parse_contact_line = _parse_bytes_line('contact', 'contact') _parse_published_line = _parse_timestamp_line('published', 'published') -_parse_extrainfo_digest_line = _parse_forty_character_hex('extra-info-digest', 'extra_info_digest') _parse_read_history_line = functools.partial(_parse_history_line, 'read-history', 'read_history_end', 'read_history_interval', 'read_history_values') _parse_write_history_line = functools.partial(_parse_history_line, 'write-history', 'write_history_end', 'write_history_interval', 'write_history_values') _parse_ipv6_policy_line = lambda descriptor, entries: setattr(descriptor, 'exit_policy_v6', stem.exit_policy.MicroExitPolicy(_value('ipv6-policy', entries))) diff --git a/test/unit/descriptor/data/server_descriptor_with_ed25519 b/test/unit/descriptor/data/server_descriptor_with_ed25519 new file mode 100644 index 0000000..2f43ced --- /dev/null +++ b/test/unit/descriptor/data/server_descriptor_with_ed25519 @@ -0,0 +1,50 @@ +@type server-descriptor 1.0 +router Truie 198.50.156.78 9001 0 9030 +identity-ed25519 +-----BEGIN ED25519 CERT----- +AQQABhWIAZTz0r0KRagr6X9SHfm4oiIuMLVhJQQmNchtkBuR5SuFAQAgBAAVkw7m +0YJgO/A8VMioco097sIOutDiM7UqqPvoIyKErk1akOm3f6VAO/juOzxEeAgzgfA7 +DiRsSjeVjp0xUdE43bXhK/8Uh+SPMwYKj47drjgTHGgzjTmlY9B/jFJ1Wgs= +-----END ED25519 CERT----- +platform Tor 0.2.7.1-alpha-dev on Linux +protocols Link 1 2 Circuit 1 +published 2015-05-28 15:44:47 +fingerprint A692 21A7 EC74 98D2 F88A 0FB7 9526 1013 FA36 CAAE +uptime 61 +bandwidth 1073741824 1073741824 9506816 +extra-info-digest 0879DB7B765218D7B3AE7557669D20307BB21CAA V609l+N6ActBveebfNbH5lQ6wHDNstDkFgyqEhBHwtA +onion-key +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBALbTpnPvhaGET+2ACtLdG6jhQXN8uVJ0iF9RwMh2hwu351yp3eVPt7os +ditUF6w7KV+6emkvLu9EBpNN7vWrpDAhRNOGTOZhZKLnGFaxp+eGNX6+5AhmiWYt +/+w+f6dvVKEjsaX3XZsMqcTBjw2hzVpHxh/AjgDx/b9mJKC85vENAgMBAAE= +-----END RSA PUBLIC KEY----- +signing-key +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBALDSt2G+Zjl20a59HZsuag913ONdnnNa/uVMRbsZZkbnNRONf2aXBGgu +wrW7XtPLeAKl+d0d5g9XnePVvefcEdKvoKNCFv6s8s3S2KB/CEkeyE7Lxx1Pc6Qx +f/jgS3T3TFHUlvtZvHLZ/3WaXMyuTTRlGadpzDkQx5oWR6aNn065AgMBAAE= +-----END RSA PUBLIC KEY----- +onion-key-crosscert +-----BEGIN CROSSCERT----- +TCcCIv38fGcSzUO+DKxudFme2XBRuDkf5FjEr+6UbtDyuDjvjJDFYagN+zMJf/4K +RyBScjyKYK6MVMxAmf25QjAGx3KHV00ozVSzlN3WDAS2iicuKYvBsehG9g/tr6mI +luS5EoSKJIlmM2jOhN1QyR+Rpi37z/E6VTksk/bd69A= +-----END CROSSCERT----- +ntor-onion-key-crosscert 0 +-----BEGIN ED25519 CERT----- +AQoABhNgARWTDubRgmA78DxUyKhyjT3uwg660OIztSqo++gjIoSuAEW8gwMcFUSD +mfkijKN6KyZxHloENGcgJMeJsR9kvfYp/u7O+VoPQ1kTxaw1lajTrnGQF+PV1MlK +niid4Nq5ZgM= +-----END ED25519 CERT----- +hidden-service-dir +contact 0x11F48D36 David Goulet <dgoulet AT ev0ke dot net> +ntor-onion-key qDcuoDpDD36bIapIbXBVhkIoiuMIXD9jNfjF1+7Vaks= +reject *:* +router-sig-ed25519 AxqrLz7QL/e+xGhhihs/rNzWsBW0Qla7Cwru1q88A5i+pcQBgfzfECiecptqYbDAsUPXMtwFsLp7Ls2BMOzvCQ +router-signature +-----BEGIN SIGNATURE----- +mSkveaqx79vzXLc6yC2+x8yZMQPe74ihw9tZJDdSOK5VqhzZOKHFM+JoD12noxQd +wgxa+IX0RG65KlguYE7NEZ7M6JOwr6r0zK/pWSZE8ZeHyt7FDx9ygc3k2ybQ6RWE +Hd7QXPiyVgs9cIgnvGFVt/5vzjMV+BELpOtehBrUJbs= +-----END SIGNATURE----- diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py index 226cdcd..4ee60f3 100644 --- a/test/unit/descriptor/server_descriptor.py +++ b/test/unit/descriptor/server_descriptor.py @@ -236,6 +236,45 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
self.assertTrue(isinstance(str(desc), str))
+ def test_with_ed25519(self): + """ + Parses a descriptor with a ed25519 identity key, as added by proposal 228 + (cross certification onionkeys). + """ + + with open(get_resource('server_descriptor_with_ed25519'), 'rb') as descriptor_file: + desc = next(stem.descriptor.parse_file(descriptor_file, 'server-descriptor 1.0', validate = True)) + + self.assertEqual('Truie', desc.nickname) + self.assertEqual('A69221A7EC7498D2F88A0FB795261013FA36CAAE', desc.fingerprint) + self.assertEqual('198.50.156.78', desc.address) + self.assertEqual(9001, desc.or_port) + self.assertEqual(None, desc.socks_port) + self.assertEqual(9030, desc.dir_port) + self.assertEqual(b'Tor 0.2.7.1-alpha-dev on Linux', desc.platform) + self.assertEqual(stem.version.Version('0.2.7.1-alpha-dev'), desc.tor_version) + self.assertEqual('Linux', desc.operating_system) + self.assertEqual(61, desc.uptime) + self.assertEqual(datetime.datetime(2015, 5, 28, 15, 44, 47), desc.published) + self.assertEqual(b'0x11F48D36 David Goulet <dgoulet AT ev0ke dot net>', desc.contact) + self.assertEqual(['1', '2'], desc.link_protocols) + self.assertEqual(['1'], desc.circuit_protocols) + self.assertEqual(False, desc.hibernating) + self.assertEqual(False, desc.allow_single_hop_exits) + self.assertEqual(False, desc.extra_info_cache) + self.assertEqual('0879DB7B765218D7B3AE7557669D20307BB21CAA', desc.extra_info_digest) + self.assertEqual(['2'], desc.hidden_service_dir) + self.assertEqual(set(), desc.family) + self.assertEqual(1073741824, desc.average_bandwidth) + self.assertEqual(1073741824, desc.burst_bandwidth) + self.assertEqual(9506816, desc.observed_bandwidth) + self.assertEqual(stem.exit_policy.ExitPolicy('reject *:*'), desc.exit_policy) + self.assertTrue('MIGJAoGBALbTpn' in desc.onion_key) + self.assertTrue('MIGJAoGBALDSt2' in desc.signing_key) + self.assertTrue('mSkveaqx79vzX' in desc.signature) + self.assertEqual(4, len(desc.get_unrecognized_lines())) + self.assertEqual('B0445BC590F004B8FD3BE922EB19EC490DBA9077', desc.digest()) + def test_cr_in_contact_line(self): """ Parses a descriptor with a huge contact line containing anomalous carriage
tor-commits@lists.torproject.org