Browse Source

additional information to send in single-pass created cell

slight tweaks to temporary VRF functions
Chelsea H. Komlo 4 years ago
parent
commit
40b49b7fe8
1 changed files with 29 additions and 19 deletions
  1. 29 19
      relay.py

+ 29 - 19
relay.py

@@ -12,18 +12,23 @@ import nacl.hash
 import nacl.bindings
 import hashlib
 
+from collections import namedtuple
+
 import network
 import dirauth
 
+VRFOutput = namedtuple('VRFOutput', 'output proof')
+
 class VRF():
-    def __init__(self, private_key):
+    def __init__(self, private_key, relaypicker):
         self.private_key = private_key
+        self.relaypicker = relaypicker
 
     def get_output(self, vrf_input):
-        output = random.choice(str(vrf_input))
+        output = self.relaypicker.pick_weighted_relay_index()
         m = hashlib.sha256()
         m.update(str(output).encode())
-        m.digest()
+        return VRFOutput(output, m.digest())
 
 class RelayNetMsg(network.NetMsg):
     """The subclass of NetMsg for messages between relays and either
@@ -199,8 +204,11 @@ class SinglePassCreatedCircuitCell(RelayCell):
     """The message for responding to circuit creation in Single-Pass Walking
     Onions."""
 
-    def __init__(self, ntor_reply):
+    def __init__(self, ntor_reply, snip, vrf_output, ttl):
         self.ntor_reply = ntor_reply
+        self.snip = snip
+        self.vrf_output = vrf_output
+        self.ttl = ttl
 
 
 class EncryptedCell(RelayCell):
@@ -521,22 +529,24 @@ class SinglePassCreatedRelayHandler:
     """Handle a SinglePassCreatedCircuitCell received by a _relay_ that
     recently received a SinglePassCreateCircuitMsg from this relay."""
 
-    def __init__(self, ntorreply, next_snip, vrf_output):
+    def __init__(self, ntorreply, next_snip, vrf_output, ttl):
+        self.ntorreply = ntorreply
         self.next_snip = next_snip
         self.vrf_output = vrf_output
-        self.ntorreply = ntorreply
+        self.ttl = ttl
 
     def received_cell(self, circhandler, cell):
         logging.debug("Handle a SinglePassCreatedCircuitCell received by a relay")
         # Remove ourselves from handling a second
         # SinglePassCreatedCircuitCell on this circuit
         circhandler.replace_celltype_handler(SinglePassCreatedCircuitCell, None)
-        logging.debug("WARNING: Unimplemented! have not yet implemented encrypting the reply directly to the client.")
+        logging.debug("Sending SinglePassCreatedCell")
 
         # Just forward a SinglePassCreatedCircuitCell back towards the
         # client
         circhandler.adjacent_circuit_handler.send_cell(
-            SinglePassCreatedCircuitCell(cell.ntor_reply, self.next_snip))
+            SinglePassCreatedCircuitCell(cell.ntor_reply, self.next_snip,
+                self.vrf_output, self.ttl))
 
 
 class CircuitHandler:
@@ -928,9 +938,10 @@ class RelayChannelManager(ChannelManager):
             deckey = nacl.hash.sha256(secret + b'upstream')
             circhandler.add_crypt_layer(enckey, deckey)
 
-            # Send the ntor reply
+            # Send the ntor reply, but no need to send the snip for the next
+            # relay or vrf proof, as this is the last relay in the circuit.
             self.send_msg(CircuitCellMsg(msg.circid,
-                SinglePassCreatedCircuitCell(reply)), peeraddr)
+                SinglePassCreatedCircuitCell(reply, None, None, 0)), peeraddr)
 
         elif isinstance(msg, SinglePassCreateCircuitMsg) and msg.ttl > 0:
             # A new circuit has arrived
@@ -960,18 +971,16 @@ class RelayChannelManager(ChannelManager):
             logging.debug("RelayChannelManager: Unimplemented! need to translate idx into endive index")
             logging.debug("RelayChannelManager: Unimplemented! need to pick the next relay using the shared secret between the client and the relay.")
 
-            # TODO temporary
-            next_hop = None
-            # make sure the next hop is not the same as ourselves or as the
-            # relay that we just received the create message from.
+            # simpulate the VRF output for now
+            vrf_output = VRF(self.onionkey,
+                    self.relaypicker).get_output(idx_as_hex)
+
+            next_hop = self.relaypicker.pick_relay_by_uniform_index(vrf_output.output)
+            logging.debug("WARNING: Unimplemented! Need to validate next hop is not null or ourselves, if it is, we should send a CLOSE cell.")
             while next_hop == None or next_hop.snipdict["idkey"] == self.idpubkey or next_hop.snipdict["addr"] == peeraddr:
-                logging.debug("WARNING: Unimplemented! Need to validate next hop is not null or ourselves, if it is, we should send a CLOSE cell.")
                 idx = self.relaypicker.pick_weighted_relay_index()
                 next_hop = self.relaypicker.pick_relay_by_uniform_index(idx)
 
-            # simpulate the VRF output for now
-            vrf_output = VRF(self.onionkey).get_output(idx)
-
             # Allocate a new circuit id to the requested next hop
             channelmgr = circhandler.channel.channelmgr
             nexthopchannel = channelmgr.get_channel_to(next_hop.snipdict["addr"])
@@ -985,7 +994,8 @@ class RelayChannelManager(ChannelManager):
             # circuit has been created
             newcirchandler.replace_celltype_handler(
                     SinglePassCreatedCircuitCell,
-                    SinglePassCreatedRelayHandler(ntorreply, next_hop, vrf_output))
+                    SinglePassCreatedRelayHandler(ntorreply, next_hop,
+                        vrf_output, msg.ttl))
 
             # Send the next create message to the next hop
             nexthopchannel.send_msg(SinglePassCreateCircuitMsg(newcircid,