[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [chutney/master] Rewrite ed25519 key loading to be more robust



commit 74a77f68897347053abea73c17e4cb045096c9c9
Author: teor <teor@xxxxxxxxxx>
Date:   Mon May 18 14:24:05 2020 +1000

    Rewrite ed25519 key loading to be more robust
    
    Tolerate being called early during bootstrap, and being called on old
    tor versions without ed25519.
---
 lib/chutney/TorNet.py | 83 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 46 insertions(+), 37 deletions(-)

diff --git a/lib/chutney/TorNet.py b/lib/chutney/TorNet.py
index 2eef368..5d28763 100644
--- a/lib/chutney/TorNet.py
+++ b/lib/chutney/TorNet.py
@@ -866,48 +866,53 @@ class LocalNodeBuilder(NodeBuilder):
 
 class LocalNodeController(NodeController):
 
-    def _setEd25519Id(self):
+    def __init__(self, env):
+        NodeController.__init__(self, env)
+        self._env = env
+
+    def _loadEd25519Id(self):
         """
-           Read the ed25519 identity key for this router, and set up the
-           'ed25519_id' entry in the Environ
+           Read the ed25519 identity key for this router, encode it using
+           base64, strip trailing padding, and return it.
+
+           If the file does not exist, returns None.
+
+           Raises a ValueError if the file appears to be corrupt.
         """
         datadir = self._env['dir']
         key_file = os.path.join(datadir, 'keys',
                                 "ed25519_master_id_public_key")
-        EXPECTED_ED25519_FILE_SIZE = 64
-        CURRENT_FILE_SIZE = os.stat(key_file).st_size
+        # If we're called early during bootstrap, the file won't have been
+        # created yet. (And some very old tor versions don't have ed25519.)
         if not os.path.exists(key_file):
-            print(("File {} does not exist. "
-                   "Are you running a very old tor version?").format(key_file))
-            return
-        elif CURRENT_FILE_SIZE != EXPECTED_ED25519_FILE_SIZE:
-            raise ValueError(("The current size of the file is {} bytes, "
-                              "which is not matching the expected value of "
-                              "{} bytes").format(CURRENT_FILE_SIZE,
-                                                 EXPECTED_ED25519_FILE_SIZE))
-        else:
-            with open(key_file, 'rb') as f:
-                ED25519_KEY_POSITION = 32
-                f.seek(ED25519_KEY_POSITION)
-                rest_file = f.read()
-                encoded_value = base64.b64encode(rest_file)
-                ed25519_id = encoded_value.decode('utf-8').replace('=', '')
-                EXPECTED_ED25519_BASE64_KEY_SIZE = 43
-                CURRENT_ED25519_BASE64_KEY_SIZE = len(ed25519_id)
-                if (CURRENT_ED25519_BASE64_KEY_SIZE !=
-                    EXPECTED_ED25519_BASE64_KEY_SIZE):
-                    raise ValueError(("The current length of the key is {}, "
-                                     "which is not matching the expected "
-                                     "length of {}")
-                                     .format(CURRENT_ED25519_BASE64_KEY_SIZE,
-                                             EXPECTED_ED25519_BASE64_KEY_SIZE))
-                else:
-                    self._env['ed25519_id'] = ed25519_id
+            debug(("File {} does not exist. Are you running a very old tor "
+                   "version?").format(key_file))
+            return None
 
-    def __init__(self, env):
-        NodeController.__init__(self, env)
-        self._env = env
-        self._setEd25519Id()
+        EXPECTED_ED25519_FILE_SIZE = 64
+        key_file_size = os.stat(key_file).st_size
+        if key_file_size != EXPECTED_ED25519_FILE_SIZE:
+            raise ValueError(
+                ("The current size of the file is {} bytes, which is not"
+                 "matching the expected value of {} bytes")
+                .format(key_file_size, EXPECTED_ED25519_FILE_SIZE))
+
+        with open(key_file, 'rb') as f:
+            ED25519_KEY_POSITION = 32
+            f.seek(ED25519_KEY_POSITION)
+            rest_file = f.read()
+            encoded_value = base64.b64encode(rest_file)
+            # tor strips trailing base64 padding
+            ed25519_id = encoded_value.decode('utf-8').replace('=', '')
+            EXPECTED_ED25519_BASE64_KEY_SIZE = 43
+            key_base64_size = len(ed25519_id)
+            if (key_base64_size != EXPECTED_ED25519_BASE64_KEY_SIZE):
+                raise ValueError(
+                    ("The current length of the key is {}, which is not "
+                     "matching the expected length of {}")
+                    .format(key_base64_size,
+                            EXPECTED_ED25519_BASE64_KEY_SIZE))
+            return ed25519_id
 
     def getNick(self):
         """Return the nickname for this node."""
@@ -921,11 +926,15 @@ class LocalNodeController(NodeController):
             return 0
 
     def getEd25519Id(self):
-        """Return the value of ed25519 key"""
+        """Return the base64-encoded ed25519 public key of this node."""
         try:
             return self._env['ed25519_id']
         except KeyError:
-            return None
+            ed25519_id = self._loadEd25519Id()
+            # cache a copy for later
+            if ed25519_id:
+                self._env['ed25519_id'] = ed25519_id
+            return ed25519_id
 
     def getBridgeClient(self):
         """Return the bridge client flag for this node."""



_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits