示例#1
0
def make_fragment(message_id, fragment_number, last_fragment, payload,
                  payload_limit):
    if fragment_number > 0b0011_1111:
        raise ValueError("Too many fragments needed for this payload.")

    if not payload and message_id != DUMMY_FRAG_ID:
        raise ValueError("No more fragments left to generate.")

    frag_byte = fragment_number

    if last_fragment:
        frag_byte |= FragmentGenerator.LAST_FRAG_FLAG

    if len(payload) < payload_limit:
        frag_byte |= FragmentGenerator.PADDING_FLAG

        padding_bytes, padding_len = padding_length_to_bytes(payload_limit -
                                                             len(payload))
    else:
        padding_len = 0
        padding_bytes = bytes()

    fragment = i2b(message_id, FRAG_ID_SIZE) + i2b(frag_byte, FRAG_FLAG_SIZE)

    fragment += padding_bytes

    fragment += payload[:payload_limit] + get_random_bytes(padding_len)

    return fragment
示例#2
0
    def parse_channel_init(self, channel_init, priv_comp):
        """Takes an already decrypted channel init message and reads the key.
        """
        self.last_interaction = time()

        msg_ctr, channel_init = cut(channel_init, CTR_PREFIX_LEN)

        self.request_replay_detector.check_replay_window(b2i(msg_ctr))

        sym_key, _, channel_init = process(priv_comp, channel_init)

        if self.key is not None:
            assert self.key == sym_key
            self.initialized = True
        else:
            self.key = sym_key

        print(self, "Init", "->", len(channel_init))

        channel_init = msg_ctr + channel_init

        # we add an empty ctr prefix, because the link encryption expects there
        # to be one, even though the channel init wasn't sym encrypted

        # todo look at this one again
        packet = CHAN_INIT_MSG_FLAG + i2b(self.out_chan_id, CHAN_ID_SIZE) + channel_init

        ChannelMid.requests.append(packet)
示例#3
0
    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
示例#4
0
    def forward_response(self, response):
        self.last_interaction = time()

        # cut the padding off
        response, _ = cut(response, -CTR_MODE_PADDING)

        msg_type, response = cut(response, MSG_TYPE_FLAG_LEN)

        msg_ctr, _ = cut(response, CTR_PREFIX_LEN)

        # todo find better way
        if msg_ctr != bytes(CTR_PREFIX_LEN):
            self.response_replay_detector.check_replay_window(b2i(msg_ctr))

        self.response_counter.next()

        cipher = ctr_cipher(self.key, int(self.response_counter))

        forward_msg = cipher.encrypt(response)

        print(self, "Data", "<-", len(forward_msg))

        response = msg_type + i2b(self.in_chan_id, CHAN_ID_SIZE) + bytes(self.response_counter) + forward_msg

        ChannelMid.responses.append(response)
示例#5
0
    def __init__(self, csv_row, port):
        self.packet_id = int(csv_row[PACKET_ID_INDEX])
        self.timestamp = float(csv_row[TIMESTAMP_INDEX])
        self.port = i2b(port, PORT_LEN)
        self.payload_len = int(csv_row[LENGTH_INDEX])

        self.payload_len -= ETHERNET_STACK_OVERHEAD
示例#6
0
def test_replay_detection_too_small():
    encryptor = LinkEncryptor(link_key)
    decryptor = LinkDecryptor(link_key)

    first_encrypted = encryptor.encrypt(msg_type + i2b(chan_id, CHAN_ID_SIZE) +
                                        msg_ctr + payload)
    first_link_counter = encryptor.counter

    for _ in range(REPLAY_WINDOW_SIZE + 1):
        encrypted = encryptor.encrypt(msg_type + i2b(chan_id, CHAN_ID_SIZE) +
                                      msg_ctr + payload)

        decryptor.decrypt(encrypted)

    assert first_link_counter not in decryptor.replay_detector.replay_window

    try:
        decryptor.decrypt(first_encrypted)
    except ReplayDetectedError:
        assert True
        return

    assert False
示例#7
0
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
示例#8
0
    def recv_response(self, response):
        self.last_interaction = time()
        """Turns the response into a MixMessage and saves its fragments for
        later sending.
        """
        frag_gen = FragmentGenerator(response)

        while frag_gen:
            print(self, "Data", "<-", len(frag_gen.udp_payload))

            fragment = frag_gen.get_data_fragment()
            packet = fragment + get_random_bytes(MIX_COUNT * CTR_PREFIX_LEN)

            ChannelExit.to_mix.append(DATA_MSG_FLAG + i2b(self.in_chan_id, CHAN_ID_SIZE) + packet)
示例#9
0
    def _get_init_message(self):
        self.request_counter.next()

        ip, port = self.dest_addr

        destination = ip2b(ip) + i2b(port, PORT_LEN)

        fragment = self._get_init_fragment()

        channel_init = gen_init_msg(self.pub_comps, self.sym_keys, destination + fragment)

        print(self, "Init", "->", len(channel_init))

        # we send a counter value with init messages for channel replay detection only
        return CHAN_INIT_MSG_FLAG + self.b_chan_id + bytes(self.request_counter) + channel_init
示例#10
0
def test_replay_detection_already_seen():
    encryptor = LinkEncryptor(link_key)
    decryptor = LinkDecryptor(link_key)

    encrypted = encryptor.encrypt(msg_type + i2b(chan_id, CHAN_ID_SIZE) +
                                  msg_ctr + payload)

    decryptor.decrypt(encrypted)

    try:
        decryptor.decrypt(encrypted)
    except ReplayDetectedError:
        assert True
        return

    assert False
示例#11
0
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
示例#12
0
    def forward_request(self, request):
        """Takes a mix fragment, already stripped of the channel id."""
        self.last_interaction = time()

        ctr, cipher_text = cut(request, CTR_PREFIX_LEN)
        ctr = b2i(ctr)

        self.request_replay_detector.check_replay_window(ctr)

        cipher = ctr_cipher(self.key, ctr)

        forward_msg = cipher.decrypt(cipher_text) + get_random_bytes(CTR_MODE_PADDING)

        print(self, "Data", "->", len(forward_msg) - CTR_PREFIX_LEN)

        ChannelMid.requests.append(DATA_MSG_FLAG + i2b(self.out_chan_id, CHAN_ID_SIZE) + forward_msg)

        timed_out = check_for_timed_out_channels(ChannelMid.table_in)

        for in_id in timed_out:
            out_id = ChannelMid.table_in[in_id].out_chan_id

            del ChannelMid.table_in[in_id]
            del ChannelMid.table_out[out_id]
示例#13
0
ip, port = "127.0.0.1", 45000
entry_addr = ("127.0.0.1", 20000)

if len(argv) > 1:
    to_send = int(argv[1])
else:
    to_send = -1

sock = socket(AF_INET, UDP)

start = time()

packets = 1

while to_send != 0:
    msg_size = randrange(MIN_MSG_SIZE, MAX_MSG_SIZE)
    pack_id = i2b(packets, 4)

    try:
        sock.sendto(
            ip2b(ip) + i2b(port, 2) + pack_id + bytes(msg_size - 4),
            entry_addr)
    except OSError:
        continue

    to_send -= 1

    sleep(1 / 20.0)

print("Sent", packets, "packets in", time() - start, "seconds.")
示例#14
0
 def send_chan_confirm(self):
     print(self, "Init", "<-", "len:", DATA_PACKET_SIZE)
     ChannelExit.to_mix.append(CHAN_CONFIRM_MSG_FLAG + i2b(self.in_chan_id, CHAN_ID_SIZE) + bytes(CTR_PREFIX_LEN) + get_random_bytes(DATA_PACKET_SIZE))
示例#15
0
def header(ip, port):
    return ip2b(ip) + i2b(port, 2)
示例#16
0
文件: Counter.py 项目: mchlnix/PyMix
 def __bytes__(self):
     return i2b(self.current_value, CTR_PREFIX_LEN)
示例#17
0
 def get_bytes(self):
     return Packet.ip + self.port + i2b(self.packet_id, 4) + bytes(
         self.payload_len)