def tlsn_msg_receiver(my_nick,counterparty_nick,ack_queue,recv_queue,message_headers,pk,seq_init=100000):
    '''Intended to be run as a thread; puts msgs sent to my_nick from counterparty_nick
    onto the Queue recv_queue, and sends acknowledgements onto ack_queue, filtering out
    messages whose headers/topics are not in message_headers, and using sequence numbering
    starting from seq_init (or 0 if seq_init is undef).
    Messages are received in chunks and decrypted using private key pk and base64 decoded, then
    reassembled according to line endings CRLF and EOL, as per tlsnotary's
    messaging protocol.
    '''
    if not initialized:
        raise Exception("TLSN Messaging not yet instantiated")
    
    if not hasattr(tlsn_msg_receiver, 'last_seq_which_i_acked'):
        if not seq_init: seq_init=0
        tlsn_msg_receiver.last_seq_which_i_acked = seq_init #static variable. Initialized only on first function's run

    chunks = []
    while True:
        eemsg = mi.msg_receiver(my_nick,counterparty_nick)
        if not eemsg: continue #note that the timeout is in the implementation layer

        #acknowledgements are not our business here; put them on the queue
        if eemsg[0].startswith('ack'):
            #acks are not encrypted
            ack_queue.put(eemsg[0][len('ack:'):])
            continue

        if len(eemsg) !=3: continue
        if not eemsg[0].startswith('seq'): continue #wrong format; old server hellos will do this

        msg_decrypted = dd(eemsg[1],pk)
        #print ("decrypted message is: ",msg_decrypted)
        if len(chunks) == 0:
            msg = [msg_decrypted.split(':')[0]] + [':'.join(msg_decrypted.split(':')[1:])]+[eemsg[2]]
        else:
            msg = [None,msg_decrypted,eemsg[2]]

        his_seq = int(eemsg[0][len('seq:'):])
        if his_seq <=  tlsn_msg_receiver.last_seq_which_i_acked:
            #the other side is out of sync, send an ack again
            mi.send_raw(' :' + counterparty_nick + ' ack:' + str(his_seq))
            continue

        #we did not receive the next seq in order
        if not his_seq == tlsn_msg_receiver.last_seq_which_i_acked +1: continue

        #else we got a new seq
        if len(chunks)==0: #a new message is starting
            if not msg[0].startswith(message_headers) : continue
            hdr = msg[0]

        #'CRLF' is used at the end of the first chunk, 'EOL' is used to show that there are no more chunks
        chunks.append(msg[1])
        mi.send_raw(' :' + counterparty_nick + ' ack:' + str(his_seq))
        tlsn_msg_receiver.last_seq_which_i_acked = his_seq
        if msg[-1]=='EOL':
            assembled_message = ''.join(chunks)
            recv_queue.put(hdr+':'+assembled_message)
            chunks = []
Exemple #2
0
def tlsn_receive_single_msg(header, pk, my_nick=None, ide=False):
    '''Non blocking receipt of a single message statelessly
    filtered on a message header, optionally prefixed by a username
    NB This is for handshake messages. All other messaging is handled
    by the tlsn_msg_receiver loop.
    'header' is not currently used but could be to filter.
    Messages received are filtered by header 'my_nick' if defined, otherwise
    all messages are received.
    Messages are decrypted using private key pk and base64 decoded
    Sequence number, plaintext message, ending and (if relevant) nick of sending party
    are returned.
    If ide (ignore decryption errors) is true, we return False on a decryption 
    error, treating the failure as receiving a handshake message from the wrong
    counterparty.
    '''
    if not initialized:
        raise Exception("TLSN Messaging not yet instantiated")

    retval = mi.receive_single_msg(my_nick)
    if not retval:
        return False
    if len(retval) != 2:
        raise Exception("Invalid return from messaging implementation module")

    msg_array, ctrprty_nick = retval
    header = msg_array[1] if my_nick else msg_array[0]
    encrypted_encoded_msg = msg_array[2] if my_nick else msg_array[1]
    ending = msg_array[-1]
    try:
        msg = dd(encrypted_encoded_msg, pk)
        seq = msg[0]
        msg = ''.join(msg[1:])
    except:
        if ide:
            return False  #means we got a message from the wrong counterparty
        raise Exception("Failure in decryption or decoding of message: ",
                        encrypted_encoded_msg)

    return ((header, int(seq), msg, ending), ctrprty_nick)
def tlsn_receive_single_msg(header, pk, my_nick=None,ide=False):
    '''Non blocking receipt of a single message statelessly
    filtered on a message header, optionally prefixed by a username
    NB This is for handshake messages. All other messaging is handled
    by the tlsn_msg_receiver loop.
    'header' is not currently used but could be to filter.
    Messages received are filtered by header 'my_nick' if defined, otherwise
    all messages are received.
    Messages are decrypted using private key pk and base64 decoded
    Sequence number, plaintext message, ending and (if relevant) nick of sending party
    are returned.
    If ide (ignore decryption errors) is true, we return False on a decryption 
    error, treating the failure as receiving a handshake message from the wrong
    counterparty.
    '''
    if not initialized:
        raise Exception("TLSN Messaging not yet instantiated")

    retval = mi.receive_single_msg(my_nick)
    if not retval:
        return False
    if len(retval) != 2:
        raise Exception ("Invalid return from messaging implementation module")

    msg_array,ctrprty_nick = retval
    header = msg_array[1] if my_nick else msg_array[0]
    encrypted_encoded_msg = msg_array[2] if my_nick else msg_array[1]
    ending = msg_array[-1]
    try:
        msg = dd(encrypted_encoded_msg,pk)
        seq = msg[0]
        msg = ''.join(msg[1:])
    except:
        if ide:
            return False #means we got a message from the wrong counterparty
        raise Exception ("Failure in decryption or decoding of message: ", encrypted_encoded_msg)

    return ((header,int(seq),msg,ending),ctrprty_nick)
Exemple #4
0
def tlsn_msg_receiver(my_nick,
                      counterparty_nick,
                      ack_queue,
                      recv_queue,
                      message_headers,
                      pk,
                      seq_init=100000):
    '''Intended to be run as a thread; puts msgs sent to my_nick from counterparty_nick
    onto the Queue recv_queue, and sends acknowledgements onto ack_queue, filtering out
    messages whose headers/topics are not in message_headers, and using sequence numbering
    starting from seq_init (or 0 if seq_init is undef).
    Messages are received in chunks and decrypted using private key pk and base64 decoded, then
    reassembled according to line endings CRLF and EOL, as per tlsnotary's
    messaging protocol.
    '''
    if not initialized:
        raise Exception("TLSN Messaging not yet instantiated")

    if not hasattr(tlsn_msg_receiver, 'last_seq_which_i_acked'):
        if not seq_init: seq_init = 0
        tlsn_msg_receiver.last_seq_which_i_acked = seq_init  #static variable. Initialized only on first function's run

    chunks = []
    while True:
        eemsg = mi.msg_receiver(my_nick, counterparty_nick)
        if not eemsg:
            continue  #note that the timeout is in the implementation layer

        #acknowledgements are not our business here; put them on the queue
        if eemsg[0].startswith('ack'):
            #acks are not encrypted
            ack_queue.put(eemsg[0][len('ack:'):])
            continue

        if len(eemsg) != 3: continue
        if not eemsg[0].startswith('seq'):
            continue  #wrong format; old server hellos will do this

        msg_decrypted = dd(eemsg[1], pk)
        #print ("decrypted message is: ",msg_decrypted)
        if len(chunks) == 0:
            msg = [msg_decrypted.split(':')[0]
                   ] + [':'.join(msg_decrypted.split(':')[1:])] + [eemsg[2]]
        else:
            msg = [None, msg_decrypted, eemsg[2]]

        his_seq = int(eemsg[0][len('seq:'):])
        if his_seq <= tlsn_msg_receiver.last_seq_which_i_acked:
            #the other side is out of sync, send an ack again
            mi.send_raw(' :' + counterparty_nick + ' ack:' + str(his_seq))
            continue

        #we did not receive the next seq in order
        if not his_seq == tlsn_msg_receiver.last_seq_which_i_acked + 1:
            continue

        #else we got a new seq
        if len(chunks) == 0:  #a new message is starting
            if not msg[0].startswith(message_headers): continue
            hdr = msg[0]

        #'CRLF' is used at the end of the first chunk, 'EOL' is used to show that there are no more chunks
        chunks.append(msg[1])
        mi.send_raw(' :' + counterparty_nick + ' ack:' + str(his_seq))
        tlsn_msg_receiver.last_seq_which_i_acked = his_seq
        if msg[-1] == 'EOL':
            assembled_message = ''.join(chunks)
            recv_queue.put(hdr + ':' + assembled_message)
            chunks = []