[tor-commits] [stem/master] Stub minimal cell decryption function

atagar at torproject.org atagar at torproject.org
Sun Aug 26 20:49:21 UTC 2018


commit 52edd22ca10d559270ee240409447351bd8639f8
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Aug 25 13:32:07 2018 -0700

    Stub minimal cell decryption function
    
    Ok, now into the meat of this sucker. Dave's branch introduces nice additions
    such as validating our backward digest and a flag to indicate if we've fully
    decrypted the cell or not.
    
    For the moment moving to a minimal decryption function that only supports what
    we did previously. Next gonna try to integrate his new features to make a
    hybrid approach that hopefully takes the best of both.
---
 stem/client/__init__.py | 22 +++++++---------------
 stem/client/cell.py     | 30 ++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/stem/client/__init__.py b/stem/client/__init__.py
index a216696a..19528d67 100644
--- a/stem/client/__init__.py
+++ b/stem/client/__init__.py
@@ -33,7 +33,7 @@ import stem.client.cell
 import stem.socket
 import stem.util.connection
 
-from stem.client.datatype import ZERO, LinkProtocol, Address, KDF
+from stem.client.datatype import ZERO, LinkProtocol, Address, KDF, split
 
 __all__ = [
   'cell',
@@ -253,22 +253,14 @@ class Circuit(object):
         raise stem.ProtocolError('Circuit response should be a series of RELAY cells, but received an unexpected size for a response: %i' % len(reply))
 
       while reply:
-        raw_cell, reply = stem.client.cell.Cell.pop(reply, self.relay.link_protocol)
+        encrypted_cell, reply = split(reply, self.relay.link_protocol.fixed_cell_length)
+        decrypted_cell, backward_key, backward_digest = stem.client.cell.RelayCell.decrypt(encrypted_cell, self.backward_key, self.backward_digest)
 
-        if raw_cell.VALUE != stem.client.cell.RelayCell.VALUE:
-          raise stem.ProtocolError('RELAY cell responses should be %i but was %i' % (stem.client.cell.RelayCell.VALUE, raw_cell.VALUE))
-        elif raw_cell.circ_id != self.id:
-          raise stem.ProtocolError('Response should be for circuit id %i, not %i' % (self.id, raw_cell.circ_id))
+        if self.id != decrypted_cell.circ_id:
+          raise stem.ProtocolError('Response should be for circuit id %i, not %i' % (self.id, decrypted_cell.circ_id))
 
-        decrypted_cell, fully_decrypted, new_backward_digest, new_backward_key = raw_cell.decrypt(self.backward_digest, self.backward_key, interpret = True)
-
-        if not fully_decrypted:
-          raise stem.ProtocolError('Response for circuit id %i was not fully decrypted, when expected to be' % self.id)
-
-        # Again, if the above raises the digest/key should remain unchanged.
-
-        self.backward_digest = new_backward_digest
-        self.backward_key = new_backward_key
+        self.backward_digest = backward_digest
+        self.backward_key = backward_key
 
         reply_cells.append(decrypted_cell)
 
diff --git a/stem/client/cell.py b/stem/client/cell.py
index 6587ebb5..3de1c731 100644
--- a/stem/client/cell.py
+++ b/stem/client/cell.py
@@ -551,6 +551,36 @@ class RelayCell(CircuitCell):
       elif stream_id and self.command in STREAM_ID_DISALLOWED:
         raise ValueError('%s relay cells concern the circuit itself and cannot have a stream id' % self.command)
 
+  @classmethod
+  def decrypt(link_protocol, content, digest, key):
+    """
+    Parse the given content as an encrypted RELAY cell.
+    """
+
+    # TODO: Fill in the above pydocs, deduplicate with the other decrypt
+    # method, yadda yadda. Starting with a minimal stub to see if this makes
+    # the Circuit class better. I'll circle back to clean up this module if it
+    # works.
+
+    if len(content) != link_protocol.fixed_cell_length:
+      raise stem.ProtocolError('RELAY cells should be %i bytes, but received %i' % (link_protocol.fixed_cell_length, len(content)))
+
+    circ_id, content = link_protocol.circ_id_size.pop(content)
+    command, payload = Size.CHAR.pop(content)
+
+    if command != RelayCell.VALUE:
+      raise stem.ProtocolError('Cannot decrypt as a RELAY cell. This had command %i instead.' % command)
+
+    key = copy.copy(key)
+    decrypted = key.update(payload)
+
+    # TODO: Integrate with check_digest() and flag for integrating if we're
+    # fully decrypted. For the moment we only handle direct responses (ie. all
+    # the cells we receive can be fully decrypted) but if we attempt to support
+    # relaying we'll need to pass along cells we can only partially decrypt.
+
+    return RelayCell._unpack(decrypted, circ_id, link_protocol), key, digest
+
   @staticmethod
   def _coerce_digest(digest):
     """





More information about the tor-commits mailing list