[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