def check_their_sig(self, enc_sig, sig_mac, usePrimes=False): my_dh_key = self.dh_keys.get_my_cur_keyid() if usePrimes: cKey = self.dh_keys.cprime m1Key = self.dh_keys.m1prime m2Key = self.dh_keys.m2prime else: cKey = self.dh_keys.c m1Key = self.dh_keys.m1 m2Key = self.dh_keys.m2 sig = OtrCrypt.aes_zero_ctr_crypt(cKey, enc_sig) #print sig byte_reader = ByteStreamReader(sig) their_dsa_key = byte_reader.get_pubkey() if their_dsa_key["cipher_code"] != list(OtrConstants["dsa_code_bytes"]): return False # now keyid their_dh_keyid = _OT.bytes_to_int(byte_reader.get_int()) self.dh_keys.associate_their_keyid(their_dh_keyid) # load their DSA public key - (y,g,p,q) their_dsa_key_tup = ( _OT.mpi_to_int(their_dsa_key["y_mpi"]), _OT.mpi_to_int(their_dsa_key["g_mpi"]), _OT.mpi_to_int(their_dsa_key["p_mpi"]), _OT.mpi_to_int(their_dsa_key["q_mpi"]) ) self.dsa_keys.load_their_key(their_dsa_key_tup) # compute their M factor self.compute_their_M_factor(usePrimes=usePrimes) # now load their signed M factor q_len = their_dsa_key["q_len"] M_sig_r_factor = _OT.bytes_to_int(byte_reader.get_n_bytes(q_len)) M_sig_s_factor = _OT.bytes_to_int(byte_reader.get_n_bytes(q_len)) assert (byte_reader.consumed_all()) if not OtrDSA.verify(self.dsa_keys.their_public_key, self.their_M, M_sig_r_factor, M_sig_s_factor): logging.debug("DID NOT VERIFY") return False # now check their MAC calc_sig_mac = OtrCrypt.get_sha256_hmac_160(m2Key, _OT.bytes_to_data(enc_sig)) if calc_sig_mac != sig_mac: logging.debug( "MAC INCORRECT" ) #print enc_sig #print calc_sig_mac #print sig_mac return False # alright, looks like everything checks out return True
def encrypt_data_message(self, msg): #global memo # encrypt the message counter = _OT.zero_pad(_OT.int_to_bytes(self.ctr), 8) enc_msg = OtrCrypt.aes_ctr_crypt(self.send_aes_key, msg, self.ctr) memo.enc_msg = enc_msg flags = [0x00] #memo.flags = flags # generate T = (my_keyid, their_keyid, next_dh, ctr, AES-CTR_ek,ctr(msg)) T = [0,2,3, flags[0]] # protocol version and msg code # my_keyid sender_keyid = _OT.zero_pad(_OT.int_to_bytes(self.my_sess_keyid), 4) #memo.sender_keyid = sender_keyid T.extend( sender_keyid ) # their_keyid recipient_keyid = _OT.zero_pad(_OT.int_to_bytes(self.their_sess_keyid), 4) #memo.recipient_keyid = recipient_keyid T.extend( recipient_keyid ) # next_dh next_dh = _OT.int_to_mpi(self.next_dh) #memo.next_dh = next_dh T.extend( next_dh ) # ctr #memo.counter = counter T.extend( counter ) # enc_msg T.extend( _OT.bytes_to_data(enc_msg) ) #memo.T = T # compute MAC_mk(T) authenticator = OtrCrypt.get_sha1_hmac(self.send_mac_key, T) #memo.authenticator = authenticator #memo.old_mac_keys = self.old_mac_keys #memo.send_mac_key = self.send_mac_key #memo.recv_mac_key = self.recv_mac_key #memo.send_aes_key = self.send_aes_key #memo.recv_aes_key = self.recv_aes_key #memo.secbytes = self.secbytes #memo.sender_factor = self.my_public_factor_to_mpi(self.my_sess_keyid) #print "SENDER" #for x in sorted(self.my_public_factors.keys()): # print (x, self.my_public_factor_to_mpi(x)) #r = raw_input() #memo.recipient_factor = self.their_public_factor_to_mpi(self.their_sess_keyid) return (flags, sender_keyid, recipient_keyid, next_dh, counter, _OT.bytes_to_data(enc_msg), authenticator, _OT.bytes_to_data(self.old_mac_keys))
def decrypt_their_public_factor(self, r_secret): self.r_secret = r_secret their_public_factor_mpi = \ OtrCrypt.aes_zero_ctr_crypt(r_secret, self.enc_gxmpi) calculated_hash = OtrCrypt.get_sha256_bytes(their_public_factor_mpi) if calculated_hash == self.hash_gxmpi: self.store_their_public_factor(_OT.mpi_to_int(their_public_factor_mpi)) return True else: return False
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)
def compute_ek_and_mk_factors(self, my_keyid, their_keyid): my_public_key = self.my_public_factors[my_keyid] their_public_key = self.their_public_factors[their_keyid] #self.compute_c_and_m_factors(my_keyid, their_keyid) if my_public_key > their_public_key: self.end = "high" self.sendbyte = 0x01 self.recvbyte = 0x02 else: self.end = "low" self.sendbyte = 0x02 self.recvbyte = 0x01 self.send_aes_key = OtrCrypt.h1(self.sendbyte, self.secbytes)[0:16] self.send_mac_key = OtrCrypt.get_sha1_bytes(self.send_aes_key)[0:20] self.recv_aes_key = OtrCrypt.h1(self.recvbyte, self.secbytes)[0:16] self.recv_mac_key = OtrCrypt.get_sha1_bytes(self.recv_aes_key)[0:20]
def get_enc_sig_mac(self, usePrimes=False): if usePrimes: m2Key = self.dh_keys.m2prime else: m2Key = self.dh_keys.m2 enc_sig_mac = OtrCrypt.get_sha256_hmac_160(m2Key, _OT.bytes_to_data(self.my_enc_sig)) self.replay.check('hash_enc_X', enc_sig_mac) return enc_sig_mac
def compute_my_M_and_X_values(self, usePrimes=False): my_dh_keyid = self.dh_keys.get_my_cur_keyid() if usePrimes: cKey = self.dh_keys.cprime m1Key = self.dh_keys.m1prime else: cKey = self.dh_keys.c m1Key = self.dh_keys.m1 # Compute the 32-byte value MB to be the SHA256-HMAC of the following data, using the key m1: mbytes = [] # gx (MPI) mbytes.extend( self.dh_keys.my_public_factor_to_mpi(my_dh_keyid) ) # gy (MPI) mbytes.extend( self.dh_keys.their_public_factor_to_mpi() ) # pubB (PUBKEY) mbytes.extend( OtrDSA.format_key(self.dsa_keys.my_public_key) ) # keyidB (INT) keyid = _OT.zero_pad(_OT.int_to_bytes(my_dh_keyid), 4) mbytes.extend( keyid ) self.replay.check('M', mbytes) my_M = OtrCrypt.get_sha256_hmac(m1Key, mbytes) self.replay.check('hash_M', my_M) # Let XB be the following structure: xbytes = [] # pubB (PUBKEY) xbytes.extend( OtrDSA.format_key(self.dsa_keys.my_public_key) ) # keyidB (INT) xbytes.extend( keyid ) # sigB(MB) (SIG) # This is the signature, using the private part of the key pubB, of the 32-byte MB # (which does not need to be hashed again to produce the signature). xbytes.extend( self.dsa_keys.sign( my_M ) ) my_X = xbytes self.replay.check('X', my_X) # Encrypt XB using AES128-CTR with key c and initial counter value 0. self.my_enc_sig = OtrCrypt.aes_zero_ctr_crypt(cKey, my_X) self.replay.check('enc_X', self.my_enc_sig)
def compute_c_and_m_factors(self, my_keyid=None, their_keyid=None): #Write the value of s as a minimum-length MPI, as specified above # (4-byte big-endian len, len-byte big-endian value). # Let this (4+len)-byte value be "secbytes". self.secbytes = _OT.int_to_mpi(self.make_shared_key(my_keyid, their_keyid)) #For a given byte b, define h2(b) to be the 256-bit output of the SHA256 hash of the # (5+len) bytes consisting of the byte b, followed by secbytes. #Let ssid be the first 64 bits of h2(0x00). self.ssid = OtrCrypt.h2(0x00, self.secbytes)[0:0+8] #Let c be the first 128 bits of h2(0x01), and let c' be the second 128 bits of h2(0x01). t = OtrCrypt.h2(0x01, self.secbytes) self.c = t[0:0+16] if self.authing: self.replay.check('c', self.c) self.cprime = t[16:16+16] if self.authing: self.replay.check('cp', self.cprime) #Let m1 be h2(0x02). self.m1 = OtrCrypt.h2(0x02, self.secbytes) if self.authing: self.replay.check('m1', self.m1) #Let m2 be h2(0x03). self.m2 = OtrCrypt.h2(0x03, self.secbytes) if self.authing: self.replay.check('m2', self.m2) #Let m1' be h2(0x04). self.m1prime = OtrCrypt.h2(0x04, self.secbytes) if self.authing: self.replay.check('m1p', self.m1prime) #Let m2' be h2(0x05). self.m2prime = OtrCrypt.h2(0x05, self.secbytes) if self.authing: self.replay.check('m2p', self.m2prime)
def compute_their_M_factor(self, usePrimes=False): my_dh_keyid = self.dh_keys.get_my_cur_keyid() their_dh_keyid = self.dh_keys.get_their_cur_keyid() if usePrimes: m1PrimeKey = self.dh_keys.m1prime else: m1PrimeKey = self.dh_keys.m1 # Compute the 32-byte value MA to be the SHA256-HMAC of the following data, using the key m1': mbytes = [] # gy (MPI) mbytes.extend( self.dh_keys.their_public_factor_to_mpi(their_dh_keyid) ) # gx (MPI) mbytes.extend( self.dh_keys.my_public_factor_to_mpi(my_dh_keyid) ) # pubA (PUBKEY) mbytes.extend( OtrDSA.format_key(self.dsa_keys.their_public_key) ) # keyidA (INT) keyid = _OT.zero_pad(_OT.int_to_bytes(their_dh_keyid), 4) mbytes.extend( keyid ) self.their_M = OtrCrypt.get_sha256_hmac(m1PrimeKey, mbytes)
def hash_my_public_factor_mpi(self, my_keyid=None): hash_gxmpi = OtrCrypt.get_sha256_bytes(self.my_public_factor_to_mpi(my_keyid)) # RCHANGE if self.authing: self.replay.check('hash_dh_factor', hash_gxmpi) hash_gxmpi_data = _OT.bytes_to_data(hash_gxmpi) return hash_gxmpi_data
def encrypt_my_public_factor_mpi(self, my_keyid=None): enc_gxmpi = OtrCrypt.aes_zero_ctr_crypt(self.r_secret, self.my_public_factor_to_mpi(my_keyid)) # RCHANGE if self.authing: self.replay.check('enc_dh_factor', enc_gxmpi) enc_gxmpi_data = _OT.bytes_to_data(enc_gxmpi) return enc_gxmpi_data