def peer_response(self, key, ticket, peer_username): # Step 1: Decrypt and split the ticket to get the information of the client ret = False ticket = CryptoLib.decryptUsingSymetricKey(key, self.sessionID, ticket) ticket = ticket.split(":") peer_address = ticket[0] peer_public_key = ticket[1] peer = Peer.Peer(peer_username, peer_address, peer_public_key) # Step 2: Generate and send contribution b = CryptoLib.generatePublicPrivateKeys(32) msg = pow(2, b, self.peerPrime) msg = CryptoLib.encryptUsingPublicKey(peer_public_key, msg) if not self.send_message(msg, peer_address[0], peer_address[1]): return ret # Step 3: Recieve peer contribution and iv and unpack it peer_contribution = self.receive_response() peer_contribution = CryptoLib.decryptUsingPrivateKey(self.clientPrivateKey, peer_contribution) peer_contribution = peer_contribution.split(":") peer_session_id = peer_contribution[1] peer_contribution = peer_contribution[0] # Construct shared key shared_key = pow(peer_contribution, b, self.peerPrime) # Step 4: Challenge Response (Two way authentication) - user sends challenge, client increments and sends # back response which is again incremented and sent back to user. All of this is done using the symmetric # key encryption with the shared key. challenge = random.randrange(1, 100000) challenge = CryptoLib.encyptUsingSymmetricKey(shared_key, peer_session_id, challenge) if not self.send_message(challenge, peer_address[0], peer_address[1]): return ret response = self.receive_response() response = CryptoLib.decryptUsingSymetricKey(shared_key, peer_session_id, response) # If authentication is successful, add the peer to list of connected peers and send back response if response == challenge + 1: response += 1 response = CryptoLib.encyptUsingSymmetricKey(shared_key, peer_session_id, response) if not self.send_message(response, peer_address[0], peer_address[1]): return ret peer.set_initialization_vector(peer_session_id) peer.set_shared_key(shared_key) self.peers[peer_address] = peer return True return False
def authenticate_me(self, pwdHash): #print "authenticate with chat server and set up session key" ret = False if self.serverPublicKey is not None: # step 1: send authentication message msg = "AUTH:" if not self.send_message(msg, self.serverAddr, self.port): return ret # step 2: receive challenge and starting number serverResponse = self.receive_response() if(serverResponse is None): return ret challengeAndStartingNum = serverResponse.split(":") challenge = int(challengeAndStartingNum[0],16) startingNum = int(challengeAndStartingNum[1]) #************************************************** # Start authentication procedure (Augmented PDM) #************************************************** # step 3: solve challenge and send APDM contribution challenge_response = self.solve_challenge(challenge, startingNum) a = CryptoLib.generateRandomKey(16) # retrieve the safe prime for the user p = genPrime.genp(self.username, self.password) # step 4: generate client contribution (2^a mod p) and send challenge response, # client user name and contribution to server Note: no need to encrypt because eavesdropper # cannot compute 2^W mod p client_contribution = pow(ChatClient.generator, int(a.encode('hex'), 16), p) msg = "CONTRIBUTION:" + str(challenge_response) + ":" + self.username + ":" + str(client_contribution) #msg = CryptoLib.encryptUsingPublicKey(self.serverPublicKey, msg) if not self.send_message(msg, self.serverAddr, self.port): return ret # step 5: receive server contribution and shared key hash serverResponse = self.receive_response() if(serverResponse is None): print "failed to receive response from server" return ret serverContributionAndHash = serverResponse.split(":") serverContribution = serverContributionAndHash[0] serverSessionKeyHash = serverContributionAndHash[1] # step 6: calculate session key and hash W = pwdHash # 2^ab mod p sharedKey1 = CryptoLib.generateSecretKey(int(serverContribution), int(a.encode('hex'), 16), p) # 2^bW mod p sharedKey2 = CryptoLib.generateSecretKey(int(serverContribution), int(W, 16), p) #print "===== W: ", W sessionKey = (str(sharedKey1) + str(sharedKey2))[0:16] if self.DBG: print "sharedKey1: %s, sharedKey2: %s, sessionKey: %s, len: %d" % \ (sharedKey1, sharedKey2, sessionKey, len(sessionKey)) # HASH(2^ab mod p, 2^bW modp) sessionKeyHash = CryptoLib.generateKeyHash(sessionKey) if(serverSessionKeyHash == sessionKeyHash): self.sessionKey = sessionKey self.sessionID = serverContributionAndHash[2] if self.DBG: print"====== session keys match!! sessionID %s, len: %d " % \ (self.sessionID, len(self.sessionID)) # step 7: send hash of encrypted session key and public key to server self.clientPrivateKey, self.clientPublicKey = CryptoLib.generatePublicPrivateKeys() validateServer = int(CryptoLib.generateRandomKey(16).encode("hex"), 16) #msg = "VALIDATE:" + sessionKeyHash + ":" + self.clientPublicKey + ":" + validateServer msg = "VALIDATE:" + sessionKeyHash + ":" + str(validateServer) + ":" + self.clientPublicKey msg = CryptoLib.encyptUsingSymmetricKey(self.sessionKey, self.sessionID, msg) if not self.send_message(msg, self.serverAddr, self.port): return ret # server signals that client has been fully authenticated response = self.receive_response() if response is None: print "Error!!! didn't receive response from server" return ret response = CryptoLib.decryptUsingSymetricKey(self.sessionKey, self.sessionID, response) response = response.split(":") if self.DBG is True: print "validateServer: %s, serverResponse: %s" % (str(validateServer), response[1]) if response[0] == "ACKNOWLEDGE" and \ int(validateServer + 1 == int(response[1])): ret = True # End of authentication with server. return ret