def test_build_auth_challenge(self): c = torpylle.Cell(Command="AUTH_CHALLENGE", Challenge='a' * 32, Methods=[]).build() assert len(c) == 5 + 32 + 2 c2 = torpylle.Cell(Command="AUTH_CHALLENGE", Challenge='a' * 32, Methods=[1]).build() assert len(c2) == 5 + 32 + 2 + 2
def send_certs(reader, writer, link_cert, id_cert): link_der = crypto.dump_certificate(crypto.FILETYPE_ASN1, link_cert) id_der = crypto.dump_certificate(crypto.FILETYPE_ASN1, id_cert) cert1 = torpylle.OrCert(Type=1, Certificate=link_der) cert2 = torpylle.OrCert(Type=2, Certificate=id_der) writer.write( bytes(torpylle.Cell(Command="CERTS", Certificates=[cert1, cert2])))
def test_netinfo(self): other = torpylle.OrAddress(Type=4, Address='127.0.0.1') this = [torpylle.OrAddress(Type=4, Address='127.0.0.1')] bites = torpylle.Cell(Command="NETINFO", OtherOrAddress=other, ThisOrAddresses=[other], Timestamp=int(time.time()))
def send_netinfo(reader, writer, their_address, my_addresses): other = torpylle.OrAddress(Type=4, Address=their_address) this = [torpylle.OrAddress(Type=4, Address=addr) for addr in my_addresses] bites = torpylle.Cell(Command="NETINFO", OtherOrAddress=other, ThisOrAddresses=this, Timestamp=int(time.time())) writer.write(bytes(bites))
def handle_create(reader, writer, node_id, seckey_b, create_cell): assert len(node_id) == 20 assert len(seckey_b.get_public().serialize()) == 32 create_hdata = create_cell.Hdata[:84] skeys, created_hdata = server(seckey_b, node_id, create_hdata) writer.write(bytes(torpylle.Cell(Command="CREATED2", Hdata=created_hdata, CircID=create_cell.CircID))) return skeys
def test_build_created2(self): node_id = b"iToldYouAboutStairs." server_key = PrivateKey() x, create_payload = client_part1(node_id, server_key.get_public()) skeys, created_payload = server(server_key, node_id, create_payload) c = torpylle.Cell(Command="CREATED2", Hdata=created_payload).build() assert len(c) == 512
async def test_queue_put_one(self, event_loop): queues = {0: asyncio.Queue()} s_reader, c_writer = await dummy_transport() c_reader, s_writer = await dummy_transport() test_cell = torpylle.Cell(Command="VERSIONS", Versions=[2, 3, 4]) queuer = CellQueuer(s_reader, s_writer, queues, {}, loop=event_loop) await queuer.put(test_cell) recvd_cell = await read_cell(c_reader, None) assert bytes(recvd_cell) == bytes(test_cell) await queuer.stop()
def decrypt_relay_cell(circuit_hops, relay_cell, direction): logger.info('decrypt_relay_cell: %s' % repr(relay_cell)) if direction not in ['fw', 'bw']: raise Exception('bad direction in decrypt_relay_cell') payload = bytes(relay_cell)[3:] for hop in circuit_hops: if direction == 'fw': payload = hop.cipher_fw.decrypt(payload) else: payload = hop.cipher_bw.decrypt(payload) pt_bytes = bytes(relay_cell)[:3] + payload logger.info('pt_bytes: %s' % pt_bytes) pt_cell = torpylle.Cell(pt_bytes) pt_copy = torpylle.Cell(pt_bytes) # TODO: this is nasty logger.info('unencr: %s' % repr(pt_cell)) if isinstance(pt_cell, torpylle.CellRelayEncrypted): logger.info('not recognized, so returning') return pt_cell # still encrypted, not destined here their_digest = pt_copy.Digest pt_copy.Digest = b'\x00\x00\x00\x00' old_state = None our_digest = None if direction == 'fw': old_state = circuit_hops[-1].hash_fw.digest() logger.info('our old digest: %s' % old_state) circuit_hops[-1].hash_fw.update(bytes(pt_copy)[3:]) our_digest = circuit_hops[-1].hash_fw.digest() else: old_state = circuit_hops[-1].hash_bw.digest() logger.info('our old digest: %s' % old_state) circuit_hops[-1].hash_bw.update(bytes(pt_copy)[3:]) our_digest = circuit_hops[-1].hash_bw.digest() # TODO: not done, need to revert state if digests don't match <==========================!!! logger.info('our digest: %s their digest: %s' % (our_digest, their_digest)) if our_digest[:4] != their_digest: raise Exception('no match') return pt_cell
async def test_two_queues(self, event_loop): c_queues = {0: asyncio.Queue()} s_queues = {0: asyncio.Queue()} s_reader, c_writer = await dummy_transport() c_reader, s_writer = await dummy_transport() test_cell = torpylle.Cell(Command="VERSIONS", Versions=[2, 3, 4]) c_queuer = CellQueuer(c_reader, c_writer, c_queues, {}, loop=event_loop) s_queuer = CellQueuer(s_reader, s_writer, s_queues, {}, loop=event_loop) await c_queuer.put(test_cell) recvd_cell = await s_queues[0].get() assert bytes(recvd_cell) == bytes(test_cell) await c_queuer.stop() await s_queuer.stop()
async def create_circuit(reader_q, writer, circid, node_id, pubkey_B): assert len(node_id) == 20 assert len(pubkey_B.serialize()) == 32 x, create_payload = client_part1(node_id, pubkey_B) writer.write(bytes(torpylle.Cell(Command="CREATE2", CircID=circid, Htype="ntor", Hdata=create_payload))) created_cell = await asyncio.wait_for(reader_q.get(), timeout=4) # Hdata should always have len=64 anyway created_hdata = created_cell.Hdata[:64] keys = client_part2(x, created_hdata, node_id, pubkey_B) logger.info('hdata: %s' % hex(struct.unpack('<L', created_hdata[:4])[0])) logger.info('hdata: %s' % hex(struct.unpack('<L', created_hdata[4:8])[0])) logger.info('hdata: %s' % hex(struct.unpack('<L', created_hdata[8:12])[0])) logger.info('hdata: %s' % hex(struct.unpack('<L', created_hdata[12:16])[0])) logger.info('digest forward: %s' % hex(struct.unpack('<L', keys[:4])[0])) logger.info('digest backward: %s' % hex(struct.unpack('<L', keys[20:24])[0])) logger.info('keys forward: %s' % hex(struct.unpack('<L', keys[40:44])[0])) logger.info('keys backward: %s' % hex(struct.unpack('<L', keys[56:60])[0])) return keys
def encrypt_relay_cell(circuit_hops, relay_cell, direction): if direction not in ['fw', 'bw']: raise Exception('bad direction in encrypt_relay_cell') logger.info('encrypting in direction %s' % direction) relay_cell.Digest = b'\x00' * 4 if direction == 'fw': logger.info('current digest %s' % circuit_hops[-1].hash_fw.hexdigest()) circuit_hops[-1].hash_fw.update(bytes(relay_cell)[3:]) relay_cell.Digest = circuit_hops[-1].hash_fw.digest()[:4] else: logger.info('current digest %s' % circuit_hops[-1].hash_bw.hexdigest()) circuit_hops[-1].hash_bw.update(bytes(relay_cell)[3:]) relay_cell.Digest = circuit_hops[-1].hash_bw.digest()[:4] logger.info('sent digest %s' % hex(struct.unpack('<L', relay_cell.Digest)[0])) logger.info('cell %s' % repr(relay_cell)) payload = bytes(relay_cell)[3:] for hop in reversed(circuit_hops): if direction == 'fw': payload = hop.cipher_fw.encrypt(payload) else: payload = hop.cipher_bw.encrypt(payload) cell = torpylle.Cell(bytes(relay_cell)[:3] + payload) return cell
def send_auth_challenge(reader, writer): c = torpylle.Cell(Command="AUTH_CHALLENGE", Challenge='a' * 32, Methods=[]) writer.write(bytes(c))
async def negotiate_version_server(reader, writer, my_versions): their_cell = await asyncio.wait_for(read_cell(reader, writer), timeout=1) writer.write(bytes(torpylle.Cell(Command="VERSIONS", Versions=my_versions))) return negotiate_version_common(their_cell, my_versions)
def test_intersection(self): their_cell = torpylle.Cell(Command="VERSIONS", Versions=[2, 3, 4]) my_versions = [2, 3] assert negotiate_version_common(their_cell, my_versions) == 3
def test_not_versions(self): their_cell = torpylle.Cell(Command="PADDING") my_versions = [2] with pytest.raises(ProtocolViolation): negotiate_version_common(their_cell, my_versions)
def test_no_intersection(self): their_cell = torpylle.Cell(Command="VERSIONS", Versions=[3, 4]) my_versions = [2] with pytest.raises(IncompatibleVersions): negotiate_version_common(their_cell, my_versions)