commit 47a331d642f766af9f45d438b16dcf675b602608 Author: Damian Johnson atagar@torproject.org Date: Fri Feb 2 13:35:56 2018 -0800
Initial circuit creation function
Finally our first function that actually interacts with a socket. Just circuit creation to start with. Still needs tests. This is the first tidbit we'll be able to integ test! --- stem/client/__init__.py | 24 ++++++++++++++++++++++-- stem/client/cell.py | 4 ++-- 2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/stem/client/__init__.py b/stem/client/__init__.py index 0accaa59..cbeed403 100644 --- a/stem/client/__init__.py +++ b/stem/client/__init__.py @@ -499,11 +499,12 @@ class KDF(collections.namedtuple('KDF', ['key_hash', 'forward_digest', 'backward return KDF(key_hash, forward_digest, backward_digest, forward_key, backward_key)
-class Circuit(collections.namedtuple('Circuit', ['id', 'forward_digest', 'backward_digest', 'forward_key', 'backward_key'])): +class Circuit(collections.namedtuple('Circuit', ['socket', 'id', 'forward_digest', 'backward_digest', 'forward_key', 'backward_key'])): """ Circuit through which requests can be made of a `Tor relay's ORPort https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt`_.
+ :var stem.socket.RelaySocket socket: socket through which this circuit has been established :var int id: circuit id :var hashlib.sha1 forward_digest: digest for forward integrity check :var hashlib.sha1 backward_digest: digest for backward integrity check @@ -512,16 +513,35 @@ class Circuit(collections.namedtuple('Circuit', ['id', 'forward_digest', 'backwa """
@staticmethod - def from_kdf(circ_id, kdf): + def create(relay_socket, circ_id, link_version): + """ + Constructs a new circuit over the given ORPort. + """ + if not stem.prereq.is_crypto_available(): raise ImportError('Circuit construction requires the cryptography module')
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend
+ create_fast_cell = stem.client.cell.CreateFastCell(circ_id) + relay_socket.send(create_fast_cell.pack(link_version)) + + response = stem.client.cell.Cell.unpack(relay_socket.recv(), link_version) + created_fast_cells = filter(lambda cell: isinstance(cell, stem.client.cell.CreatedFastCell), response) + + if not created_fast_cells: + raise ValueError('We should get a CREATED_FAST response from a CREATE_FAST request') + + created_fast_cell = created_fast_cells[0] + kdf = KDF.from_value(create_fast_cell.key_material + created_fast_cell.key_material) ctr = modes.CTR(ZERO * (algorithms.AES.block_size / 8))
+ if created_fast_cell.derivative_key != kdf.key_hash: + raise ValueError('Remote failed to prove that it knows our shared key') + return Circuit( + relay_socket, circ_id, hashlib.sha1(kdf.forward_digest), hashlib.sha1(kdf.backward_digest), diff --git a/stem/client/cell.py b/stem/client/cell.py index 9b0c3274..2bae4fc5 100644 --- a/stem/client/cell.py +++ b/stem/client/cell.py @@ -277,7 +277,7 @@ class RelayCell(CircuitCell): """ Command concerning a relay circuit.
- :var stem.client.RelayCommand command: reason the circuit is being closed + :var stem.client.RelayCommand command: command to be issued :var int command_int: integer value of our command :var bytes data: payload of the cell :var int digest: running digest held with the relay @@ -295,7 +295,7 @@ class RelayCell(CircuitCell): VALUE = 3 IS_FIXED_SIZE = True
- def __init__(self, circ_id, command, data, digest, stream_id = 0): + def __init__(self, circ_id, command, data, digest = 0, stream_id = 0): super(RelayCell, self).__init__(circ_id) self.command, self.command_int = stem.client.RelayCommand.get(command) self.data = data
tor-commits@lists.torproject.org