def build_extend_cell(handshake_type: str, x_bytes: bytes, gx_bytes: bytes, circ_id: int, onion_key, hop2_ip, hop2_port) -> Cell: """ The method used to build a Extend/Extend2 cell :param handshake_type: The handshake type. TAP or ntor. :param x_bytes: The diffie hellman private key as a bytes object :param gx_bytes: The diffie hellman public key as a bytes object :param circ_id: The circuit ID :param onion_key: The onion key of the next hop used in hybrid_encrypt method :param lspec: The link specifier as a string :return: The extend Cell object """ client_h_data = CoreCryptoRSA.hybrid_encrypt(gx_bytes, onion_key) nspec = 1 # Always keep this 1 to avoid going to hell lspec = bytearray(IPv4Address(hop2_ip).packed) + pack('!H', int(hop2_port)) extend_cell_payload = RelayExtendPayload(nspec, RelayExtendPayload.LSTYPE_ENUM['TLS_TCP_IPV4'], RelayExtendPayload.LSTYPE_LSLEN_ENUM['TLS_TCP_IPV4'], lspec, CreateCellPayload.CREATE_HANDSHAKE_TYPE[handshake_type], CreateCellPayload.CREATE_HANDSHAKE_LEN[handshake_type], client_h_data) relay_cell_payload = RelayCellPayload(RelayCellPayload.RELAY_CMD_ENUM['RELAY_EXTEND2'], 0, 0, b'', Cell.PAYLOAD_LEN - 11, extend_cell_payload) relay_extend_cell = Cell(circ_id, Cell.CMD_ENUM['RELAY'], Cell.PAYLOAD_LEN, relay_cell_payload) return relay_extend_cell
def build_extended_cell(y, gy, streamID: int, circ_id: int, gx: str, recognized) -> Cell: """ The method to build the extended Cell object :param y: :param gy: :param streamID: :param circ_id: :param gx: :param recognized: :return: The Extended Cell """ gxy = CoreCryptoDH.compute_dh_shared_key(y, gx) kdf_dict = CoreCryptoRSA.kdf_tor(gxy) server_h_data = TapSHData(gy, kdf_dict['KH']) # Construct extended2 payload extended_cell_payload_relay = RelayExtendedPayload(RelayExtendedPayload.TAP_S_HANDSHAKE_LEN, server_h_data) # Calculate digest from the extended2 payload payload_dict = { 'HLEN': extended_cell_payload_relay.HLEN, 'HDATA': extended_cell_payload_relay.HDATA } digest = CoreCryptoMisc.calculate_digest(payload_dict) # Construct the Relay cell with extended2 payload which is the payload for the Cell class extended_cell_payload = RelayCellPayload(RelayCellPayload.RELAY_CMD_ENUM['EXTENDED2'], recognized, streamID, digest, Cell.PAYLOAD_LEN - 11, extended_cell_payload_relay) # Construct the actual cell extended_cell = Cell(circ_id, Cell.CMD_ENUM['RELAY'], Cell.PAYLOAD_LEN, extended_cell_payload) return extended_cell
def parse_encoded_extended_cell(cell_bytes: bytes) -> Cell: cell_tuple = Parser.parse_basic_cell(cell_bytes) relay_cell_payload_tuple = Parser.parse_encoded_relay_cell(cell_bytes) part_fmt_str1 = '=H' part_tuple1 = unpack(part_fmt_str1, relay_cell_payload_tuple[5][0:2]) fmt_str = '=H' + str(part_tuple1[0]) + 's' relay_extended_payload_tuple = unpack(fmt_str, relay_cell_payload_tuple[5][0:2+part_tuple1[0]]) h_data_fmt_str = '='+str(CC.DH_LEN)+'s'+str(CC.HASH_LEN)+'s' h_data_tuple = unpack(h_data_fmt_str, relay_extended_payload_tuple[1]) server_h_data = TapSHData(h_data_tuple[0], h_data_tuple[1]) relay_extended_payload = RelayExtendedPayload(relay_extended_payload_tuple[0], server_h_data) relay_cell_payload = RelayCellPayload(relay_cell_payload_tuple[0], relay_cell_payload_tuple[1], relay_cell_payload_tuple[2], relay_cell_payload_tuple[3], relay_cell_payload_tuple[4], relay_extended_payload) extended_cell = Cell(cell_tuple[0], cell_tuple[1], cell_tuple[2], relay_cell_payload) return extended_cell
def build_relay_connected_cell(CIRCID: int, StreamID, kdf_dict, IPv4_address : str,TTL : int) -> Cell: """ :param CIRCID: The Circuit ID :param StreamID: The Stream ID :param kdf_dict: A dictionary (key) to encrypt data :param IPv4_address: The IPv4 address to which the connection was made [4 octets] :param TTL: A number of seconds (TTL) for which the address may be cached [4 octets] :return: """ # Encrypt the values by packing and unpacking enc_StreamID = unpack('!H', CoreCryptoSymmetric.encrypt_for_hop(pack('!H', StreamID), kdf_dict))[0] enc_relay_payload_len = unpack('!H',CoreCryptoSymmetric.encrypt_for_hop(pack('!H', Cell.PAYLOAD_LEN - 11),kdf_dict))[0] enc_IPv4_address = unpack('!I', CoreCryptoSymmetric.encrypt_for_hop(pack('!I', int(IPv4Address(IPv4_address))), kdf_dict))[0] enc_TTL = unpack('!I',CoreCryptoSymmetric.encrypt_for_hop(pack('!I', TTL), kdf_dict))[0] # enc_digest = CoreCryptoSymmetric.encrypt_for_hop(digest, kdf_dict) relay_connected_cell_payload = RelayConnectedPayload(enc_IPv4_address, enc_TTL) relay_cell_payload = RelayCellPayload(RelayCellPayload.RELAY_CMD_ENUM['RELAY_CONNECTED'], 0, enc_StreamID, b'', enc_relay_payload_len, relay_connected_cell_payload) # Construct the actual cell relay_cell = Cell(CIRCID, Cell.CMD_ENUM['RELAY'], Cell.PAYLOAD_LEN, relay_cell_payload) return relay_cell
def build_relay_data_cell(CIRCID: int, StreamID, kdf_dict1, kdf_dict2, kdf_dict3, http_req: str): enc_StreamID = unpack( '!H', CoreCryptoSymmetric.encrypt_from_origin(pack('!H', StreamID), kdf_dict1, kdf_dict2, kdf_dict3))[0] enc_relay_data_len = unpack( '!H', CoreCryptoSymmetric.encrypt_from_origin( pack('!H', Cell.PAYLOAD_LEN - 3), kdf_dict1, kdf_dict2, kdf_dict3))[0] #encrypting the http_req encoded_http_req = http_req.encode() http_req_len = len(http_req) enc_http_req = unpack( '!http_req_lenc', CoreCryptoSymmetric.encrypt_from_origin( pack('!http_req_lenc', StreamID), kdf_dict1, kdf_dict2, kdf_dict3))[0] #creating the relay cell payload with http_req as payload relay_cell_payload = RelayCellPayload( RelayCellPayload.RELAY_CMD_ENUM['RELAY_DATA'], 0, enc_StreamID, b'', enc_relay_data_len, http_req) #creating the complete cell relay_data_cell = Cell(CIRCID, Cell.CMD_ENUM['RELAY'], Cell.PAYLOAD_LEN, relay_cell_payload) return relay_data_cell
def parse_encoded_connected_cell(cell_bytes: bytes)-> Cell: cell_tuple = Parser.parse_basic_cell(cell_bytes) relay_payload_tuple = Parser.parse_encoded_relay_cell(cell_bytes) relay_connected_tuple=unpack('=II',relay_payload_tuple[5][0:8]) relay_connected_obj=RelayConnectedPayload(relay_connected_tuple[0],relay_connected_tuple[1]) relay_payload_obj=RelayCellPayload(relay_payload_tuple[0],relay_payload_tuple[1],relay_payload_tuple[2],relay_payload_tuple[3],relay_payload_tuple[4],relay_connected_obj) cell=Cell(cell_tuple[0],cell_tuple[1],cell_tuple[2],relay_payload_obj) return cell
def build_extended_cell_from_created_cell(circ_id: int, hlen, hdata) -> Cell: """ The method to build the Extended Cell from a received Created Cell :param circ_id: The circuit ID :param hlen: The handshake len(from Created Cell) :param hdata: The handshake Data of type TapCHData(from Created Cell) :return: The Extended Cell """ relay_extended_cell_payload = RelayExtendedPayload(hlen, hdata) extended_cell_payload = RelayCellPayload(RelayCellPayload.RELAY_CMD_ENUM['RELAY_EXTENDED2'], 0, 0, b'', Cell.PAYLOAD_LEN - 11, relay_extended_cell_payload) # Construct the actual cell extended_cell = Cell(circ_id, Cell.CMD_ENUM['RELAY'], Cell.PAYLOAD_LEN, extended_cell_payload) return extended_cell
def parse_encoded_data_cell(cell_bytes: bytes) -> Cell: cell_tuple = Parser.parse_basic_cell(cell_bytes) relay_cell_payload_tuple = Parser.parse_encoded_relay_cell(cell_bytes) relay_data_payload = relay_cell_payload_tuple[5] relay_cell_payload = RelayCellPayload(relay_cell_payload_tuple[0], relay_cell_payload_tuple[1], relay_cell_payload_tuple[2], relay_cell_payload_tuple[3], relay_cell_payload_tuple[4], relay_data_payload) relay_data_cell = Cell(cell_tuple[0], cell_tuple[1], cell_tuple[2], relay_cell_payload) return relay_data_cell
def parse_encoded_extend_cell(cell_bytes: bytes) -> Cell: cell_tuple = Parser.parse_basic_cell(cell_bytes) relay_cell_payload_tuple = Parser.parse_encoded_relay_cell(cell_bytes) part_fmt_str1 = '=BBB' part_tuple1 = unpack(part_fmt_str1, relay_cell_payload_tuple[5][0:3]) part_fmt_str2 = '=BBB' + str(part_tuple1[2]) + 's' + 'HH' part_tuple2 = unpack( part_fmt_str2, relay_cell_payload_tuple[5][0:(3 + part_tuple1[2] + 2 + 2)]) fmt_str = '=BBB' + str(part_tuple1[2]) + 's' + 'HH' + str( part_tuple2[5]) + 's' relay_extend_payload_tuple = unpack( fmt_str, relay_cell_payload_tuple[5][0:(3 + part_tuple1[2] + 2 + 2 + part_tuple2[5])]) h_data_fmt_str = '=' + str(CC.PK_PAD_LEN) + 's' + str( CC.KEY_LEN) + 's' + str( CC.PK_ENC_LEN - CC.PK_PAD_LEN - CC.KEY_LEN) + 's' + str( CC.DH_LEN - (CC.PK_ENC_LEN - CC.PK_PAD_LEN - CC.KEY_LEN)) + 's' h_data_tuple = unpack(h_data_fmt_str, relay_extend_payload_tuple[6]) h_data = TapCHData(h_data_tuple[0], h_data_tuple[1], h_data_tuple[2], h_data_tuple[3]) relay_extend_payload = RelayExtendPayload( relay_extend_payload_tuple[0], relay_extend_payload_tuple[1], relay_extend_payload_tuple[2], relay_extend_payload_tuple[3], relay_extend_payload_tuple[4], relay_extend_payload_tuple[5], h_data) relay_cell_payload = RelayCellPayload(relay_cell_payload_tuple[0], relay_cell_payload_tuple[1], relay_cell_payload_tuple[2], relay_cell_payload_tuple[3], relay_cell_payload_tuple[4], relay_extend_payload) extend_cell = Cell(cell_tuple[0], cell_tuple[1], cell_tuple[2], relay_cell_payload) return extend_cell
def parse_encoded_begin_cell(cell_bytes: bytes) -> Cell: cell_tuple = Parser.parse_basic_cell(cell_bytes) relay_cell_payload_tuple = Parser.parse_encoded_relay_cell(cell_bytes) fmt_str = '=6sI' relay_begin_payload_tuple = unpack(fmt_str, relay_cell_payload_tuple[5][0:6+4]) relay_begin_payload = RelayBeginPayload(relay_begin_payload_tuple[0], relay_begin_payload_tuple[1]) relay_cell_payload = RelayCellPayload(relay_cell_payload_tuple[0], relay_cell_payload_tuple[1], relay_cell_payload_tuple[2], relay_cell_payload_tuple[3], relay_cell_payload_tuple[4], relay_begin_payload) begin_cell = Cell(cell_tuple[0], cell_tuple[1], cell_tuple[2], relay_cell_payload) return begin_cell
def build_begin_cell(addrport: bytes, flag_dict, circ_id: int, recognized: int, streamID: int, kdf_dict1: Dict, kdf_dict2: Dict, kdf_dict3: Dict) -> Cell: """ The method to build a Begin Cell :param addrport: :param flag_dict: :param circ_id: :param recognized: :param streamID: :return: The Begin Cell object """ flags = int(0) flags |= flag_dict['IPV6_PREF'] flags |= (flag_dict['IPV4_NOT_OK'] << 1) flags |= (flag_dict['IPV6_OK'] << 2) digest_dict = { 'addrPort': addrport, 'flags': flags, 'relayCMD': RelayCellPayload.RELAY_CMD_ENUM['RELAY_BEGIN'], 'recognized': recognized, 'streamID': streamID, 'relayPayloadLen': Cell.PAYLOAD_LEN - 11 } digest = b'' # CoreCryptoMisc.calculate_digest(digest_dict) # Encrypt the values by packing and unpacking enc_addrport = CoreCryptoSymmetric.encrypt_from_origin(addrport, kdf_dict1, kdf_dict2, kdf_dict3) enc_flags = unpack('!I', CoreCryptoSymmetric.encrypt_from_origin(pack('!I', flags), kdf_dict1, kdf_dict2, kdf_dict3))[0] enc_relay_cmd = RelayCellPayload.RELAY_CMD_ENUM['RELAY_BEGIN'] # unpack('!B', CoreCryptoSymmetric.encrypt_from_origin(pack('!B', RelayCellPayload.RELAY_CMD_ENUM['RELAY_BEGIN']), kdf_dict1, kdf_dict2, kdf_dict3))[0] enc_recognized = unpack('!H', CoreCryptoSymmetric.encrypt_from_origin(pack('!H', recognized), kdf_dict1, kdf_dict2, kdf_dict3))[0] enc_stream_id = unpack('!H', CoreCryptoSymmetric.encrypt_from_origin(pack('!H', streamID), kdf_dict1, kdf_dict2, kdf_dict3))[0] enc_relay_payload_len = unpack('!H', CoreCryptoSymmetric.encrypt_from_origin(pack('!H', Cell.PAYLOAD_LEN - 11), kdf_dict1, kdf_dict2, kdf_dict3))[0] enc_digest = CoreCryptoSymmetric.encrypt_from_origin(digest, kdf_dict1, kdf_dict2, kdf_dict3) relay_begin_payload = RelayBeginPayload(enc_addrport, enc_flags) relay_cell_payload = RelayCellPayload(enc_relay_cmd, enc_recognized, enc_stream_id, enc_digest, enc_relay_payload_len, relay_begin_payload) begin_cell = Cell(circ_id, Cell.CMD_ENUM['RELAY'], Cell.PAYLOAD_LEN, relay_cell_payload) return begin_cell