def hybrid_encrypt(message: bytes, pk: rsa.RSAPublicKey) -> TapCHData: """ This method is the hybrid encrypt outlined in the Tor spec 0.4 section :param message: The message to be encrypted :param pk: The RSA public to encrypt the message with :return: The object TapCHData that has the client handshake data """ # First convert the message to a byte array so that we can slice it etc. message = bytearray(message) if len(message ) <= CryptoConstants.PK_ENC_LEN - CryptoConstants.PK_PAD_LEN: # Then encrypt the message using the onion key p = pk.encrypt( message, padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) # Create the TAP_H_DATA object padding_bytes = bytes(CryptoConstants.PK_PAD_LEN) tap_h_data = TapCHData(padding_bytes, None, p, None) else: k = bytearray(os.urandom(CryptoConstants.KEY_LEN)) m1 = message[0:CryptoConstants.PK_ENC_LEN - CryptoConstants.PK_PAD_LEN - CryptoConstants.KEY_LEN] m2 = message[CryptoConstants.PK_ENC_LEN - CryptoConstants.PK_PAD_LEN - CryptoConstants.KEY_LEN:] p1 = pk.encrypt( bytes(k + m1), padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA1()), algorithm=hashes.SHA1(), label=None)) nonce = bytes( CryptoConstants.KEY_LEN) # all bytes are 0, nonce is the IV cipher = Cipher(algorithms.AES(k), modes.CTR(nonce), backend=default_backend()) encryptor = cipher.encryptor() p2 = encryptor.update(m2) + encryptor.finalize() print(p1, len(p1)) print(p2, len(p2)) print(m2, len(m2)) # tap_h_data = TapCHData(bytearray(p1)[CryptoConstants.PK_ENC_LEN - CryptoConstants.PK_PAD_LEN:], # bytearray(p1)[0:CryptoConstants.KEY_LEN], # bytearray(p1)[CryptoConstants.KEY_LEN:(CryptoConstants.PK_ENC_LEN - CryptoConstants.PK_PAD_LEN)], # p2) tap_h_data = TapCHData( bytearray(p1)[0:CryptoConstants.PK_PAD_LEN], bytearray(p1)[CryptoConstants.PK_PAD_LEN:( CryptoConstants.PK_PAD_LEN + CryptoConstants.KEY_LEN)], bytearray(p1)[(CryptoConstants.PK_PAD_LEN + CryptoConstants.KEY_LEN):], p2) return tap_h_data
def parse_encoded_create_cell(cell_bytes: bytes) -> Cell: cell_tuple = Parser.parse_basic_cell(cell_bytes) hlen = CreateCellPayload.CREATE_HANDSHAKE_LEN['TAP'] payload_fmt_str = '=HH'+str(hlen)+'s' create_cell_payload_tuple = unpack(payload_fmt_str, cell_tuple[3][0:(2+2+hlen)]) 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, create_cell_payload_tuple[2]) h_data = TapCHData(h_data_tuple[0], h_data_tuple[1], h_data_tuple[2], h_data_tuple[3]) create_cell_payload = CreateCellPayload(create_cell_payload_tuple[0], create_cell_payload_tuple[1], h_data) create_cell = Cell(cell_tuple[0], cell_tuple[1], cell_tuple[2], create_cell_payload) return create_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