def respond_to_dh_commit(self, msg): logging.debug("Responding to DH Commit") send_dh_key = True if self.auth.auth_state_is("AUTHSTATE_NONE"): # Reply with a D-H Key Message, and transition authstate to AUTHSTATE_AWAITING_REVEALSIG. pass # pick it up in the 'if' below elif self.auth.auth_state_is("AUTHSTATE_AWAITING_DHKEY"): #This is the trickiest transition in the whole protocol. It indicates that you have # already sent a D-H Commit message to your correspondent, but that he either # didn't receive it, or just didn't receive it yet, and has sent you one as well. # The symmetry will be broken by comparing the hashed gx you sent in your D-H Commit # Message with the one you received, considered as 32-byte unsigned big-endian values. my_dh_keyid = self.auth.dh_keys.get_my_cur_keyid() my_hashed_gxmpi = self.auth.dh_keys.hash_my_public_factor_mpi(my_dh_keyid) their_hashed_gxmpi = _OT.data_to_bytes(msg.hash_gxmpi_data) my_hash_as_int = _OT.bytes_to_int(my_hashed_gxmpi) their_hash_as_int = _OT.bytes_to_int(their_hashed_gxmpi) if my_hash_as_int > their_hash_as_int: # If yours is the higher hash value: # Ignore the incoming D-H Commit message, but resend your D-H Commit message. self.auth.dh_keys.mark_my_key_as_used(my_dh_keyid) enc_gxmpi_data = self.auth.dh_keys.encrypt_my_public_factor_mpi(my_dh_keyid) hash_gxmpi_data = self.auth.dh_keys.hash_my_public_factor_mpi(my_dh_keyid) response = self.message_factory().create_dh_commit(enc_gxmpi_data, hash_gxmpi_data) self.replay.check('msg_dh_commit', response.jabber_msg.getBody()) send_dh_key = False self.client.send(response.jabber_msg) if send_dh_key: my_dh_keyid = self.auth.dh_keys.get_my_cur_keyid() self.auth.dh_keys.mark_my_key_as_used(my_dh_keyid) # this is g**y formatted as an MPI (4 byte length prepended) # our D-H secret is y (with g**x the shared key is g**(xy)) gympi = self.auth.dh_keys.my_public_factor_to_mpi(my_dh_keyid) # SAVE their info self.auth.dh_keys.store_their_commitment( _OT.data_to_bytes(msg.enc_gxmpi_data), _OT.data_to_bytes(msg.hash_gxmpi_data) ) # ok, now make dh_key message response = self.message_factory().create_dh_key(gympi) self.replay.check('msg_dh_key', response.jabber_msg.getBody()) self.auth.set_auth_state("AUTHSTATE_AWAITING_REVEALSIG") self.client.send(response.jabber_msg) return None # nothing for user
def respond_to_reveal_sig(self, msg): logging.debug("Responding to Reveal Sig") if not self.auth.auth_state_is("AUTHSTATE_AWAITING_REVEALSIG"): return None # nothing for user # Now decrypt and check their DH factor my_dh_keyid = self.auth.dh_keys.get_my_cur_keyid() it_checks_out = self.auth.dh_keys.decrypt_their_public_factor( _OT.data_to_bytes(msg.revealed_key_data) ) if not it_checks_out: err_msg = self.message_factory() err_msg.create_error('Committed DH factor incorrect') self.client.send(err_msg.jabber_msg) return None # nothing for user raise Exception('stop here - committed DH factor incorrect') # calculate the factors we'll need self.auth.dh_keys.compute_c_and_m_factors() # check their sig it_checks_out = self.auth.check_their_sig(_OT.data_to_bytes(msg.enc_sig_data), msg.sig_mac) if not it_checks_out: err_msg = self.message_factory() err_msg.create_error('Signature incorrect') self.client.send(err_msg.jabber_msg) return None # nothing for user #raise Exception('stop here - signature incorrect') # ok, now make our sig message # load DSA key self.auth.dsa_keys.load_my_key() self.auth.compute_my_M_and_X_values(usePrimes=True) enc_sig_data = self.auth.get_enc_sig() sig_mac = self.auth.get_enc_sig_mac(usePrimes=True) response = self.message_factory().create_signature(enc_sig_data, sig_mac) self.replay.check('msg_signature', response.jabber_msg.getBody()) self.client.send(response.jabber_msg) self.auth.set_auth_state("AUTHSTATE_NONE") self.auth.set_message_state("MSGSTATE_ENCRYPTED") self.auth.dh_keys.reset_session() self.auth.authing = False self.auth.dh_keys.authing = False return None # nothing for user
def respond_to_signature(self, msg): logging.debug("Responding to Signiature") if not self.auth.auth_state_is("AUTHSTATE_AWAITING_SIG"): return None # nothing for user # check their sig it_checks_out = self.auth.check_their_sig(_OT.data_to_bytes(msg.enc_sig_data), msg.sig_mac, usePrimes=True) if not it_checks_out: err_msg = self.message_factory() err_msg.create_error('Signature incorrect') self.client.send(err_msg.jabber_msg) return None # nothing for user #raise Exception('stop here - signature incorrect') self.auth.set_auth_state("AUTHSTATE_NONE") self.auth.set_message_state("MSGSTATE_ENCRYPTED") self.auth.dh_keys.reset_session() self.auth.authing = False self.auth.dh_keys.authing = False logging.debug( "SUCESSFULLY AUTHENTICATED!" ) return None
def receive_data_message(self, msg): #global memo self.my_sess_keyid = _OT.bytes_to_int(msg.recipient_keyid) self.their_sess_keyid = _OT.bytes_to_int(msg.sender_keyid) logging.debug( "KEYIDS %d %d " % (self.my_sess_keyid, self.their_sess_keyid)) if len(msg.next_dh) > 4: logging.debug( "GOT NEXT DH" ) logging.debug( msg.next_dh ) self.associate_their_keyid(self.their_sess_keyid+1, _OT.mpi_to_int(msg.next_dh)) self.update_next_counter(self.my_sess_keyid, self.their_sess_keyid, _OT.bytes_to_int(msg.counter)) logging.debug( (msg.counter, _OT.int_to_bytes(self.ctr)) ) self.compute_c_and_m_factors(self.my_sess_keyid, self.their_sess_keyid) self.compute_ek_and_mk_factors(self.my_sess_keyid, self.their_sess_keyid) #assert memo.sender_keyid == msg.sender_keyid #assert memo.recipient_keyid == msg.recipient_keyid #assert memo.next_dh == msg.next_dh #assert memo.counter == msg.counter #assert memo.enc_msg == _OT.data_to_bytes(msg.enc_msg) T = [0,2,3, msg.flags[0]] # protocol version and type code # my_keyid T.extend( msg.sender_keyid ) # their_keyid T.extend( msg.recipient_keyid ) # next_dh T.extend( msg.next_dh ) # ctr T.extend( msg.counter ) # enc_msg logging.debug(("ENC DATA: ", msg.enc_msg)) T.extend( msg.enc_msg ) #assert memo.T == T #print memo.sender_factor #print "RECVER" #for x in sorted(self.their_public_factors.keys()): # print (x, self.their_public_factor_to_mpi(x)) #r = raw_input() #assert memo.sender_factor == self.their_public_factor_to_mpi(self.their_sess_keyid) #assert memo.recipient_factor == self.my_public_factor_to_mpi(self.my_sess_keyid) #assert memo.secbytes == self.secbytes # compute MAC_mk(T) auth_check = OtrCrypt.get_sha1_hmac(self.recv_mac_key, T) if auth_check != msg.authenticator: logging.debug( ("got: ", auth_check) ) logging.debug( ("exp: ", msg.authenticator) ) #print self.recv_mac_key, self.send_mac_key #print memo.send_mac_key raise Exception("mac fail") return OtrCrypt.aes_ctr_crypt(self.recv_aes_key, _OT.data_to_bytes(msg.enc_msg), msg.counter)