[tor-commits] [sbws/master] Store relays' ed25519 master key

pastly at torproject.org pastly at torproject.org
Thu Jun 14 13:29:50 UTC 2018


commit a73e50f2b2e3345934731c4c1e6a6e67b5251d0e
Author: juga0 <juga at riseup.net>
Date:   Mon May 28 10:41:59 2018 +0000

    Store relays' ed25519 master key
    
    * RelayList is now a list of RelayNS instead of RouterStatusEntryV3
      to have master_key_ed25519 as an attribute
    * create pytest fixture to start Tor with tests
    * create test to check master_key_ed25519
---
 sbws/lib/relaylist.py            | 57 +++++++++++++++++++++++++++++++++++++++-
 tests/unit/conftest.py           | 16 ++++++++++-
 tests/unit/lib/test_relaylist.py | 13 +++++++++
 3 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/sbws/lib/relaylist.py b/sbws/lib/relaylist.py
index aeae3eb..6d0743d 100644
--- a/sbws/lib/relaylist.py
+++ b/sbws/lib/relaylist.py
@@ -1,3 +1,5 @@
+from stem.descriptor.router_status_entry import RouterStatusEntryV3
+
 import sbws.util.stem as stem_utils
 from stem import Flag
 from stem import DescriptorUnavailable
@@ -11,6 +13,18 @@ from sbws.globals import resolve
 log = logging.getLogger(__name__)
 
 
+class RelayNS(RouterStatusEntryV3):
+    """Inherit from RouterStatusEntryV3 and add the attribute
+    master_key_ed25519.
+
+    :param str ed25519: the ed25519 master key base 64 encoded.
+    """
+    def __init__(self, ed25519=None, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        if ed25519 is not None:
+            self.master_key_ed25519 = ed25519
+
+
 class RelayList:
     ''' Keeps a list of all relays in the current Tor network and updates it
     transparently in the background. Provides useful interfaces for getting
@@ -68,6 +82,40 @@ class RelayList:
         # return [r for r in relays if r.measured is not None]
         return [r for r in relays if not r.is_unmeasured]
 
+    def relay_ed25519_master_key(self, ns):
+        """Obtain ed25519 master key of the relay represented by
+        the network status relay line.
+
+        :param RouterStatusEntryV3 ns: the network status relay
+        :returns: str, the ed25519 master key base 64 encoded without
+            trailing '='s.
+        """
+        # In theory this is never going to be the case?
+        if ns.identifier is None or ns.identifier_type != 'ed25519':
+            log.debug('Getting microdescriptor to obtain ed25519 identity.')
+            mdesc = self._controller.get_microdescriptor(ns.fingerprint, None)
+            if mdesc is not None:
+                if 'ed25519' in mdesc.identifiers.keys():
+                    ed25519 = mdesc.identifiers['ed25519'].rstrip('=')
+                    log.debug('Found ed25519 master key.')
+                    return ed25519
+                log.debug('No ed25519 master-key found')
+            log.debug('Could not get microdescriptor')
+            # In case Tor can not retrive microdescriptors,
+            # try with server descriptors.
+            log.debug('Getting server descriptor to obtain '
+                      'ed25519 master key.')
+            sdesc = self._controller.get_server_descriptor(ns.fingerprint,
+                                                           None)
+            if sdesc is not None:
+                ed25519 = sdesc.ed25519_master_key().rstrip('=')
+                log.debug('Found ed25519 master key.')
+                return ed25519
+            log.debug('Could not get server descriptor')
+            return None
+        log.debug('Relay has already ed25519 master key')
+        return ns.identifier
+
     def exits_can_exit_to(self, host, port):
         '''
         Return exits that can MOST LIKELY exit to the given host:port. **host**
@@ -131,7 +179,14 @@ class RelayList:
     def _init_relays(self):
         c = self._controller
         assert stem_utils.is_controller_okay(c)
-        return [ns for ns in c.get_network_statuses()]
+        relays = []
+        # for each network status relay, obtain the ed25519 master key
+        # and generate a new list of RelayNS objects
+        for ns in c.get_network_statuses():
+            ed25519 = self.relay_ed25519_master_key(ns)
+            rns = RelayNS(ed25519=ed25519, content=ns._raw_contents)
+            relays.append(rns)
+        return relays
 
     def _refresh(self):
         self._relays = self._init_relays()
diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py
index 4d0b2f6..2847fe1 100644
--- a/tests/unit/conftest.py
+++ b/tests/unit/conftest.py
@@ -2,8 +2,9 @@ from sbws.lib.resultdump import ResultError
 from sbws.lib.resultdump import ResultSuccess
 from sbws.lib.resultdump import Result
 from sbws.lib.resultdump import write_result_to_datadir
-from sbws.util.config import get_config
+from sbws.util.config import get_config, _get_default_config
 from sbws.util.parser import create_parser
+import sbws.util.stem as stem_utils
 import sbws.core.init
 from tempfile import TemporaryDirectory
 import pytest
@@ -61,6 +62,19 @@ def datadir(request):
     return D(request.fspath.dirpath("data"))
 
 
+ at pytest.fixture()
+def start_tor(request, tmpdir):
+    """Star Tor or connect to existing socket in a temporal directory."""
+    conf = _get_default_config()
+    home = tmpdir.join('.sbws')
+    conf['paths']['sbws_home'] = home.strpath
+    controller, _ = stem_utils.init_controller(
+                                 path=conf['tor']['control_socket'])
+    if not controller:
+        controller = stem_utils.launch_tor(conf)
+    return controller
+
+
 @pytest.fixture(scope='session')
 def parser():
     return create_parser()
diff --git a/tests/unit/lib/test_relaylist.py b/tests/unit/lib/test_relaylist.py
new file mode 100644
index 0000000..cdb71c2
--- /dev/null
+++ b/tests/unit/lib/test_relaylist.py
@@ -0,0 +1,13 @@
+from sbws.lib.relaylist import RelayList
+
+
+def test_relaylist_master_key_ed25519(start_tor):
+    # This test starts tor, so it is slow. And it will fail whenever there are
+    # network problems
+    controller = start_tor
+    rl = RelayList(None, None, controller)
+    relay = [r for r in rl.relays if r.nickname == 'moria1'][0]
+    assert relay.fingerprint == '9695DFC35FFEB861329B9F1AB04C46397020CE31'
+    assert relay.identifier is None
+    assert relay.master_key_ed25519 == \
+        'yp0fwtp4aa/VMyZJGz8vN7Km3zYet1YBZwqZEk1CwHI'





More information about the tor-commits mailing list