def test_gen_init_msg(): priv1 = params.group.gensecret() priv2 = params.group.gensecret() priv3 = params.group.gensecret() pub1 = params.group.expon_base([priv1]) pub2 = params.group.expon_base([priv2]) pub3 = params.group.expon_base([priv3]) passes = 100 for _ in range(passes): chan_keys = [gen_sym_key(), gen_sym_key(), gen_sym_key()] payload = get_random_bytes(100) proc_chan_keys = [] message = gen_init_msg([pub1, pub2, pub3], chan_keys, payload) for priv_key in [priv1, priv2, priv3]: proc_chan_key, proc_payload, message = process(priv_key, message) proc_chan_keys.append(proc_chan_key) assert chan_keys == proc_chan_keys assert payload == proc_payload
def __init__(self, src_addr, dest_addr, pub_comps): self.src_addr = src_addr self.dest_addr = dest_addr self.chan_id = ChannelEntry.random_channel() self.b_chan_id = i2b(self.chan_id, CHAN_ID_SIZE) self.pub_comps = pub_comps print(self, "New Channel", self.dest_addr) ChannelEntry.table[self.chan_id] = self self.sym_keys = [] self.request_counter = Counter(CHANNEL_CTR_START) self.replay_detector = ReplayDetector(start=CHANNEL_CTR_START) for _ in self.pub_comps: self.sym_keys.append(gen_sym_key()) self.packets = [] self.mix_msg_store = MixMessageStore() self.last_interaction = time() self.allowed_to_send = False
def gen_init_msg(pub_mix_keys, channel_keys, payload): assert len(pub_mix_keys) == len(channel_keys) y_mix_1, y_mix_2, y_mix_3 = pub_mix_keys x_msg_1 = params.group.gensecret() y_msg_1 = params.group.expon_base([x_msg_1]) k_disp_1 = params.group.expon(y_mix_1, [x_msg_1]) blind_1 = gen_blind(k_disp_1) x_msg_2 = params.group.expon(x_msg_1, [blind_1]) k_disp_2 = params.group.expon(y_mix_2, [x_msg_2]) blind_2 = gen_blind(k_disp_2) x_msg_3 = params.group.expon(x_msg_2, [blind_2]) k_disp_3 = params.group.expon(y_mix_3, [x_msg_3]) chan_key_onion = gen_sym_key() * 3 payload_onion = payload for k_disp, k_chan in zip([k_disp_3, k_disp_2, k_disp_1], reversed(channel_keys)): cipher = ctr_cipher(params.get_aes_key(k_disp), 0) chan_key_onion = cipher.encrypt(k_chan + chan_key_onion[0:-SYM_KEY_LEN]) payload_onion = cipher.encrypt(payload_onion) return y_msg_1.export() + chan_key_onion + payload_onion
def send_sym_key(self): """ Generate symmetric key for session and send to server """ self.sym_key = gen_sym_key(168) e_sym_key = self.encrypt_sym_key(self.sym_key) packet = {'type': 'sym_key'} packet['key'] = e_sym_key packet = encode_dict(packet) self.srv_sock.sendall(packet)
def test_encrypt_fragment(): channel = ChannelEntry(src_addr, dest_addr, public_keys) sym_key = gen_sym_key() channel.sym_keys = [sym_key] * MIX_COUNT fragment = FragmentGenerator(bytes(100)).get_data_fragment() packet1 = channel._encrypt_fragment(fragment) packet2 = fragment counter = 1 for _ in range(MIX_COUNT): cipher = ctr_cipher(sym_key, counter) packet2 = i2b(counter, CTR_PREFIX_LEN) + cipher.encrypt(packet2) assert packet1 == packet2
def process(priv_mix_key, message): y_msg, chan_key_onion, payload_onion = cut_init_message(message) k_disp = params.group.expon(y_msg, [priv_mix_key]) cipher = ctr_cipher(params.get_aes_key(k_disp), 0) k_chan, chan_key_onion = cut(cipher.decrypt(chan_key_onion), SYM_KEY_LEN) chan_key_onion += gen_sym_key() payload_onion = cipher.decrypt(payload_onion) blind_1 = gen_blind(k_disp) y_msg_2 = params.group.expon(y_msg, [blind_1]) message = y_msg_2.export() + chan_key_onion + payload_onion return k_chan, payload_onion, message
def test_decrypt_fragment(): channel = ChannelEntry(src_addr, dest_addr, public_keys) sym_key = gen_sym_key() channel.sym_keys = [sym_key] * MIX_COUNT fragment = FragmentGenerator(bytes(100)).get_data_fragment() fragment = channel._encrypt_fragment(fragment) packet1 = channel._decrypt_fragment(fragment) for _ in range(MIX_COUNT): msg_ctr, fragment = cut(fragment, CTR_PREFIX_LEN) cipher = ctr_cipher(sym_key, b2i(msg_ctr)) fragment = cipher.decrypt(fragment) packet2 = fragment assert packet1 == packet2
def test_replay_detection(): channel = ChannelEntry(src_addr, dest_addr, public_keys) counter = 1234 sym_key = gen_sym_key() channel.sym_keys = [sym_key] * MIX_COUNT print("Counter: {}".format(counter)) packet = FragmentGenerator(bytes(100)).get_data_fragment() packet = channel._encrypt_fragment(packet) channel._receive_response_fragment(packet) try: channel._receive_response_fragment(packet) assert False except ReplayDetectedError: assert True packet = channel._encrypt_fragment(packet) channel._receive_response_fragment(packet)
from Counter import Counter from LinkEncryption import LinkEncryptor, LinkDecryptor from ReplayDetection import ReplayDetectedError from constants import DATA_MSG_FLAG, CHAN_ID_SIZE, REPLAY_WINDOW_SIZE, CHANNEL_CTR_START from util import get_random_bytes, i2b, gen_sym_key payload = get_random_bytes(200) msg_type = DATA_MSG_FLAG chan_id = 128 msg_ctr = bytes(Counter(CHANNEL_CTR_START)) link_key = gen_sym_key() def test_link_encryption(): encryptor = LinkEncryptor(link_key) decryptor = LinkDecryptor(link_key) encrypted = encryptor.encrypt(msg_type + i2b(chan_id, CHAN_ID_SIZE) + msg_ctr + payload) chan_id2, msg_ctr2, payload2, msg_type2 = decryptor.decrypt(encrypted) assert int(encryptor.counter) in decryptor.replay_detector assert chan_id == chan_id2 assert msg_ctr == msg_ctr2 assert payload == payload2 assert msg_type == msg_type2 def test_replay_detection_already_seen():