Browse Source

Merge branch 'master' of git-crysp.uwaterloo.ca:walkingonions

Ian Goldberg 4 years ago
parent
commit
26a77c646f
4 changed files with 134 additions and 12 deletions
  1. 25 7
      client.py
  2. 1 1
      dirauth.py
  3. 12 0
      network.py
  4. 96 4
      relay.py

+ 25 - 7
client.py

@@ -141,6 +141,11 @@ class TelescopingExtendedHandler:
 
         nexthopidx = None
         while nexthopidx is None:
+            # Relays make sure that when the extend to a relay, they are not
+            # extending to themselves. So here, we just need to make sure that
+            # this ID is not the same as the guard ID, to protect against the
+            # guard and exit being the same relay
+            print("WARNING: Unimplemented! Need to check that sampled ID is not the same as the guard.")
             nexthopidx = self.channelmgr.relaypicker.pick_weighted_relay_index()
             logging.warning("Unimplemented! Need to check if this idx is in the list of circhandlers idxs")
 
@@ -450,8 +455,10 @@ if __name__ == '__main__':
     clisent = 0
     clirecv = 0
 
-    if len(sys.argv) < 2:
-        print("must pass in network mode: options are vanilla, telescoping, or single-pass.")
+    if len(sys.argv) < 3:
+        print("Must pass in network mode and snip auth mode!")
+        print("Network options are vanilla, telescoping, or single-pass.")
+        print("SNIP auth options are merkle or threshold.")
         sys.exit(0)
 
     logging.basicConfig(level=logging.DEBUG)
@@ -461,7 +468,10 @@ if __name__ == '__main__':
         print("Not a valid network mode: " + network_mode)
         sys.exit(0)
 
-    #TODO Add a command-line switch to set Merkle or Threshold
+    snipauth_mode = network.SNIPAuthMode.string_to_type(sys.argv[2])
+    if network_mode == -1:
+        print("Not a valid SNIP authentication mode: " + snipauth_mode)
+        sys.exit(0)
 
     # Initialize the (non-cryptographic) random seed
     random.seed(1)
@@ -470,11 +480,19 @@ if __name__ == '__main__':
         network.thenetwork.set_wo_style(network.WOMode.VANILLA,
             network.SNIPAuthMode.NONE)
     elif network_mode == network.WOMode.TELESCOPING:
-        network.thenetwork.set_wo_style(network.WOMode.TELESCOPING,
-            network.SNIPAuthMode.MERKLE)
+        if snipauth_mode == network.SNIPAuthMode.MERKLE:
+            network.thenetwork.set_wo_style(network.WOMode.TELESCOPING,
+                network.SNIPAuthMode.MERKLE)
+        else:
+            network.thenetwork.set_wo_style(network.WOMode.TELESCOPING,
+                network.SNIPAuthMode.THRESHSIG)
     elif network_mode == network.WOMode.SINGLEPASS:
-        network.thenetwork.set_wo_style(network.WOMode.SINGLEPASS,
-            network.SNIPAuthMode.MERKLE)
+        if snipauth_mode == network.SNIPAuthMode.MERKLE:
+            network.thenetwork.set_wo_style(network.WOMode.SINGLEPASS,
+                network.SNIPAuthMode.MERKLE)
+        else:
+            network.thenetwork.set_wo_style(network.WOMode.SINGLEPASS,
+                network.SNIPAuthMode.THRESHSIG)
     else:
         sys.exit("Received unsupported network mode, exiting.")
 

+ 1 - 1
dirauth.py

@@ -300,7 +300,7 @@ class RelayPicker:
 
     def pick_relay_by_uniform_index(self, idx):
         """Pass in a uniform random index random(0,totbw-1) to get a
-        relay selected weighted by bw."""
+        relay's descriptor or snip (depending on the network mode) selected weighted by bw."""
         if network.thenetwork.womode == network.WOMode.VANILLA:
             relays = self.consensus.consdict['relays']
         else:

+ 12 - 0
network.py

@@ -42,6 +42,18 @@ class SNIPAuthMode(Enum):
     MERKLE      = 1  # Merkle trees
     THRESHSIG   = 2  # Threshold signatures
 
+    # We only need to differentiate between merkle and telescoping on the
+    # command line input, Vanilla always takes a NONE type but nothing else
+    # does.
+    def string_to_type(type_input):
+        reprs = {'merkle': SNIPAuthMode.MERKLE,
+                'telesocping': SNIPAuthMode.THRESHSIG }
+
+        if type_input in reprs.keys():
+            return reprs[type_input]
+
+        return -1
+
 
 class EntType(Enum):
     """The different types of entities in the system."""

+ 96 - 4
relay.py

@@ -789,13 +789,17 @@ class ChannelManager:
 class RelayChannelManager(ChannelManager):
     """The subclass of ChannelManager for relays."""
 
-    def __init__(self, myaddr, dirauthaddrs, onionprivkey, idpubkey, perfstats):
+    def __init__(self, myaddr, dirauthaddrs, onionprivkey, idpubkey,
+            path_selection_key, perfstats):
         super().__init__(myaddr, dirauthaddrs, perfstats)
         self.onionkey = onionprivkey
         self.idpubkey = idpubkey
         if network.thenetwork.womode != network.WOMode.VANILLA:
             self.endive = None
 
+        if network.thenetwork.womode == network.WOMode.SINGLEPASS:
+            self.path_selection_key = path_selection_key
+
     def get_consensus(self):
         """Download a fresh consensus (and ENDIVE if using Walking
         Onions) from a random dirauth."""
@@ -878,6 +882,52 @@ class RelayChannelManager(ChannelManager):
         elif isinstance(msg, SinglePassCreateCircuitMsg):
             # A new circuit has arrived
             circhandler = channel.new_circuit_with_circid(msg.circid)
+            # Create the ntor reply for the circuit-extension key
+            (reply, secret), blinded_client_pubkey = NTor.reply(self.onionkey, self.idpubkey,
+                    msg.ntor_request, self.perfstats,  b'circuit')
+
+            # Set up the circuit to use the shared secret established from the
+            # circuit extension key
+            enckey = nacl.hash.sha256(secret + b'downstream')
+            deckey = nacl.hash.sha256(secret + b'upstream')
+            circhandler.add_crypt_layer(enckey, deckey)
+
+            print("WARNING: Unimplemented! Should check the TTL, if it isn't \
+                    zero, decriment it and pass it along. Otherwise, just reply \
+                    without extending.")
+
+            # here, we will directly extend the circuit ourselves, after doing
+            # the following:
+            # 1. determining the next relay using the client's path selection
+            #    key in conjunction with our own
+            # 2. blinding each of the client's public keys to send to the next
+            #    hop.
+            idx, blinded_client_pubkey = Sphinx.server(msg.client_path_selection_key,
+            self.path_selection_key, b'circuit', False, self.perfstats)
+
+            sys.exit("TODO convert shared secret into integer type modulo alpha")
+            nexthop = self.relaypicker.pick_relay_by_uniform_index(idx)
+            if nexthop == None:
+                print("WARNING: Unimplemented! Need to validate next hop is not null, if it is, we should send a CLOSE cell.")
+
+            # Add a handler for once the next relay replies to say that the
+            # circuit has been created
+            # be at most one on this circuit).
+            circhandler.replace_celltype_handler(
+                    SinglePassCreatedCircuitCell,
+                    SinglePassCreatedCircuitHandler(ntorreply, next_hop))
+
+#            # Allocate a new circuit id to the requested next hop
+#            channelmgr = circhandler.channel.channelmgr
+#            nexthopchannel = channelmgr.get_channel_to(next_snip.snipdict["addr"])
+#            newcircid, newcirchandler = nexthopchannel.new_circuit()
+#
+#            # Send the next create message to the next hop
+#            # TODO add the correct interface here
+#            self.send_msg(CircuitCellMsg(msg.circid,
+#                    SinglePassCreateCircuitCell(newcircid, ntorrequest,
+#                        next_client_path_selection_key)), peeraddr)
+#
             sys.exit("have not yet implemented circuit handling for single-pass in relays")
         else:
             return super().received_msg(msg, peeraddr, channel)
@@ -914,9 +964,14 @@ class Relay(network.Server):
         network.thenetwork.wantepochticks(self, True, end=True)
         network.thenetwork.wantepochticks(self, True)
 
+        if network.thenetwork.womode == network.WOMode.SINGLEPASS:
+            self.path_selection_key = nacl.public.PrivateKey.generate()
+        else:
+            self.path_selection_key = None
+
         # Create the RelayChannelManager connection manager
         self.channelmgr = RelayChannelManager(self.netaddr, dirauthaddrs,
-                self.onionkey, self.idkey.verify_key, self.perfstats)
+                self.onionkey, self.idkey.verify_key, self.path_selection_key, self.perfstats)
 
         # Initially, we're not a fallback relay
         self.is_fallbackrelay = False
@@ -967,6 +1022,10 @@ class Relay(network.Server):
         descdict["addr"] = self.netaddr
         descdict["bw"] = self.bw
         descdict["flags"] = self.flags
+
+        if network.thenetwork.womode == network.WOMode.SINGLEPASS:
+            descdict["path_selection_key"] = self.path_selection_key
+
         desc = dirauth.RelayDescriptor(descdict)
         desc.sign(self.idkey, self.perfstats)
         dirauth.RelayDescriptor.verify(desc, self.perfstats)
@@ -1017,8 +1076,41 @@ if __name__ == '__main__':
     # Initialize the (non-cryptographic) random seed
     random.seed(1)
 
-    network.thenetwork.set_wo_style(network.WOMode.TELESCOPING,
-            network.SNIPAuthMode.MERKLE)
+    if len(sys.argv) < 3:
+        print("Must pass in network mode and snip auth mode!")
+        print("Network options are vanilla, telescoping, or single-pass.")
+        print("SNIP auth options are merkle or threshold.")
+        sys.exit(0)
+
+    network_mode = network.WOMode.string_to_type(sys.argv[1])
+    if network_mode == -1:
+        print("Not a valid network mode: " + network_mode)
+        sys.exit(0)
+
+    snipauth_mode = network.SNIPAuthMode.string_to_type(sys.argv[2])
+    if network_mode == -1:
+        print("Not a valid SNIP authentication mode: " + snipauth_mode)
+        sys.exit(0)
+
+    if network_mode == network.WOMode.VANILLA:
+        network.thenetwork.set_wo_style(network.WOMode.VANILLA,
+            network.SNIPAuthMode.NONE)
+    elif network_mode == network.WOMode.TELESCOPING:
+        if snipauth_mode == network.SNIPAuthMode.MERKLE:
+            network.thenetwork.set_wo_style(network.WOMode.TELESCOPING,
+                network.SNIPAuthMode.MERKLE)
+        else:
+            network.thenetwork.set_wo_style(network.WOMode.TELESCOPING,
+                network.SNIPAuthMode.THRESHSIG)
+    elif network_mode == network.WOMode.SINGLEPASS:
+        if snipauth_mode == network.SNIPAuthMode.MERKLE:
+            network.thenetwork.set_wo_style(network.WOMode.SINGLEPASS,
+                network.SNIPAuthMode.MERKLE)
+        else:
+            network.thenetwork.set_wo_style(network.WOMode.SINGLEPASS,
+                network.SNIPAuthMode.THRESHSIG)
+    else:
+        sys.exit("Received unsupported network mode, exiting.")
 
     # Start some dirauths
     numdirauths = 9