commit 4a504c8922ff66cf414538f4e5cbd84c504ebcce Author: Damian Johnson atagar@torproject.org Date: Mon Aug 24 09:43:05 2015 -0700
Bridge extrainfo support for ed25519
Accounting for bridge extrainfo descriptor parsing of ed25519. It replaces the two new fields with a couple different ones. Need clarification on the second though. --- stem/descriptor/extrainfo_descriptor.py | 32 +++++++++++++------- .../data/bridge_extrainfo_descriptor_with_ed25519 | 25 +++++++++++++++ test/unit/descriptor/extrainfo_descriptor.py | 17 ++++++++++- 3 files changed, 62 insertions(+), 12 deletions(-)
diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py index 7373620..5b986b4 100644 --- a/stem/descriptor/extrainfo_descriptor.py +++ b/stem/descriptor/extrainfo_descriptor.py @@ -535,6 +535,7 @@ def _parse_hs_stats(keyword, stat_attribute, extra_attribute, descriptor, entrie
_parse_identity_ed25519_line = _parse_key_block('identity-ed25519', 'ed25519_certificate', 'ED25519 CERT') +_parse_master_key_ed25519_line = _parse_simple_line('master-key-ed25519', 'ed25519_certificate_hash') _parse_geoip_db_digest_line = _parse_forty_character_hex('geoip-db-digest', 'geoip_db_digest') _parse_geoip6_db_digest_line = _parse_forty_character_hex('geoip6-db-digest', 'geoip6_db_digest') _parse_dirreq_v2_resp_line = functools.partial(_parse_dirreq_line, 'dirreq-v2-resp', 'dir_v2_responses', 'dir_v2_responses_unknown') @@ -573,6 +574,7 @@ _parse_geoip_client_origins_line = functools.partial(_parse_geoip_to_count_line, _parse_entry_ips_line = functools.partial(_parse_geoip_to_count_line, 'entry-ips', 'entry_ips') _parse_bridge_ips_line = functools.partial(_parse_geoip_to_count_line, 'bridge-ips', 'bridge_ips') _parse_router_sig_ed25519_line = _parse_simple_line('router-sig-ed25519', 'ed25519_signature') +_parse_router_digest_sha256_line = _parse_simple_line('router-digest-sha256', 'router_digest_sha256') _parse_router_digest_line = _parse_forty_character_hex('router-digest', '_digest') _parse_router_signature_line = _parse_key_block('router-signature', 'signature', 'SIGNATURE')
@@ -590,9 +592,6 @@ class ExtraInfoDescriptor(Descriptor): port, args) tuple, these usually appear on bridges in which case all of those are **None**
- :var ed25519_certificate str: base64 encoded ed25519 certificate - :var ed25519_signature str: signature of this document using ed25519 - **Bi-directional connection usage:**
:var datetime conn_bi_direct_end: end of the sampling interval @@ -695,9 +694,6 @@ class ExtraInfoDescriptor(Descriptor): .. versionchanged:: 1.4.0 Added the hs_stats_end, hs_rend_cells, hs_rend_cells_attr, hs_dir_onions_seen, and hs_dir_onions_seen_attr attributes. - - .. versionchanged:: 1.5.0 - Added the ed25519_certificate and ed25519_signature attributes. """
ATTRIBUTES = { @@ -708,9 +704,6 @@ class ExtraInfoDescriptor(Descriptor): 'geoip6_db_digest': (None, _parse_geoip6_db_digest_line), 'transport': ({}, _parse_transport_line),
- 'ed25519_certificate': (None, _parse_identity_ed25519_line), - 'ed25519_signature': (None, _parse_router_sig_ed25519_line), - 'conn_bi_direct_end': (None, _parse_conn_bi_direct_line), 'conn_bi_direct_interval': (None, _parse_conn_bi_direct_line), 'conn_bi_direct_below': (None, _parse_conn_bi_direct_line), @@ -790,8 +783,6 @@ class ExtraInfoDescriptor(Descriptor):
PARSER_FOR_LINE = { 'extra-info': _parse_extra_info_line, - 'identity-ed25519': _parse_identity_ed25519_line, - 'router-sig-ed25519': _parse_router_sig_ed25519_line, 'geoip-db-digest': _parse_geoip_db_digest_line, 'geoip6-db-digest': _parse_geoip6_db_digest_line, 'transport': _parse_transport_line, @@ -900,16 +891,25 @@ class RelayExtraInfoDescriptor(ExtraInfoDescriptor): 'GETINFO extra-info/digest/*', cached descriptors, and metrics (`specification https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt`_).
+ :var ed25519_certificate str: base64 encoded ed25519 certificate + :var ed25519_signature str: signature of this document using ed25519 :var str signature: ***** signature for this extrainfo descriptor
***** attribute is required when we're parsed with validation + + .. versionchanged:: 1.5.0 + Added the ed25519_certificate and ed25519_signature attributes. """
ATTRIBUTES = dict(ExtraInfoDescriptor.ATTRIBUTES, **{ + 'ed25519_certificate': (None, _parse_identity_ed25519_line), + 'ed25519_signature': (None, _parse_router_sig_ed25519_line), 'signature': (None, _parse_router_signature_line), })
PARSER_FOR_LINE = dict(ExtraInfoDescriptor.PARSER_FOR_LINE, **{ + 'identity-ed25519': _parse_identity_ed25519_line, + 'router-sig-ed25519': _parse_router_sig_ed25519_line, 'router-signature': _parse_router_signature_line, })
@@ -925,13 +925,23 @@ class BridgeExtraInfoDescriptor(ExtraInfoDescriptor): """ Bridge extra-info descriptor (`bridge descriptor specification https://collector.torproject.org/formats.html#bridge-descriptors`_) + + :var str ed25519_certificate_hash: sha256 hash of the original identity-ed25519 + :var str router_digest_sha256: **todo**, needs clarification + + .. versionchanged:: 1.5.0 + Added the ed25519_certificate_hash and router_digest_sha256 attributes. """
ATTRIBUTES = dict(ExtraInfoDescriptor.ATTRIBUTES, **{ + 'ed25519_certificate_hash': (None, _parse_master_key_ed25519_line), + 'router_digest_sha256': (None, _parse_router_digest_sha256_line), '_digest': (None, _parse_router_digest_line), })
PARSER_FOR_LINE = dict(ExtraInfoDescriptor.PARSER_FOR_LINE, **{ + 'master-key-ed25519': _parse_master_key_ed25519_line, + 'router-digest-sha256': _parse_router_digest_sha256_line, 'router-digest': _parse_router_digest_line, })
diff --git a/test/unit/descriptor/data/bridge_extrainfo_descriptor_with_ed25519 b/test/unit/descriptor/data/bridge_extrainfo_descriptor_with_ed25519 new file mode 100644 index 0000000..0030c45 --- /dev/null +++ b/test/unit/descriptor/data/bridge_extrainfo_descriptor_with_ed25519 @@ -0,0 +1,25 @@ +@type bridge-extra-info 1.3 +extra-info Unnamed B8AB331047F1C1637EFE07FB1B94CCC0FE0ABFFA +master-key-ed25519 VigmhxML9uw8CT1XeGqZ8KLMhKk6AOKnChQt24usBbI +published 2015-08-21 16:08:15 +write-history 2015-08-21 12:51:16 (14400 s) 2371584,40206336,45142016,8745984,6049792,1072128 +read-history 2015-08-21 12:51:16 (14400 s) 5175296,43838464,50509824,13580288,8732672,4001792 +dirreq-write-history 2015-08-21 12:51:16 (14400 s) 1630208,565248,29696,28672,1993728,581632 +dirreq-read-history 2015-08-21 12:51:16 (14400 s) 1024,3072,5120,4096,285696,11264 +geoip-db-digest 6882B8663F74C23E26E3C2274C24CAB2E82D67A2 +geoip6-db-digest F063BD5247EB9829E6B9E586393D7036656DAF44 +dirreq-stats-end 2015-08-21 12:51:16 (86400 s) +dirreq-v3-ips ie=8,in=8,kz=8,nl=8,qa=8 +dirreq-v3-reqs ie=8,in=8,kz=8,nl=8,qa=8 +dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,not-modified=0,busy=0 +dirreq-v3-direct-dl complete=0,timeout=0,running=0 +dirreq-v3-tunneled-dl complete=4,timeout=4,running=0 +transport scramblesuit +transport obfs3 +transport obfs4 +bridge-stats-end 2015-08-21 12:51:21 (86400 s) +bridge-ips ie=8,in=8,kz=8,nl=8,qa=8 +bridge-ip-versions v4=8,v6=0 +bridge-ip-transports <OR>=8,obfs3=8,obfs4=8 +router-digest-sha256 7DSOQz9eGgjDX6GT7qcrVViK8yqJD4aoEnuhdAgYtgA +router-digest 3DBE6840376F3EC277002396832788DB2FB38393 diff --git a/test/unit/descriptor/extrainfo_descriptor.py b/test/unit/descriptor/extrainfo_descriptor.py index b4bc34f..fa68e62 100644 --- a/test/unit/descriptor/extrainfo_descriptor.py +++ b/test/unit/descriptor/extrainfo_descriptor.py @@ -143,7 +143,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw """
with open(get_resource('extrainfo_descriptor_with_ed25519'), 'rb') as descriptor_file: - desc = next(stem.descriptor.parse_file(descriptor_file, 'extra-info 1.0', validate = True)) + desc = next(stem.descriptor.parse_file(descriptor_file, validate = True))
self.assertEqual('silverfoxden', desc.nickname) self.assertEqual('4970B1DC3DBC8D82D7F1E43FF44B28DBF4765A4E', desc.fingerprint) @@ -151,6 +151,21 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw self.assertEqual('g6Zg7Er8K7C1etmt7p20INE1ExIvMRPvhwt6sjbLqEK+EtQq8hT+86hQ1xu7cnz6bHee+Zhhmcc4JamV4eiMAw', desc.ed25519_signature) self.assertEqual([], desc.get_unrecognized_lines())
+ def test_bridge_with_ed25519(self): + """ + Parses a bridge descriptor with a ed25519 identity key. + """ + + with open(get_resource('bridge_extrainfo_descriptor_with_ed25519'), 'rb') as descriptor_file: + desc = next(stem.descriptor.parse_file(descriptor_file, validate = True)) + + self.assertEqual('Unnamed', desc.nickname) + self.assertEqual('B8AB331047F1C1637EFE07FB1B94CCC0FE0ABFFA', desc.fingerprint) + self.assertFalse(hasattr(desc, 'ed25519_certificate')) + self.assertEqual('VigmhxML9uw8CT1XeGqZ8KLMhKk6AOKnChQt24usBbI', desc.ed25519_certificate_hash) + self.assertEqual('7DSOQz9eGgjDX6GT7qcrVViK8yqJD4aoEnuhdAgYtgA', desc.router_digest_sha256) + self.assertEqual([], desc.get_unrecognized_lines()) + def test_minimal_extrainfo_descriptor(self): """ Basic sanity check that we can parse an extrainfo descriptor with minimal