def solve_challenge(self, challenge, num): """ Solve challenge set by server :param challenge: server challenge :param num: starting value :return: number """ if self.DBG: print " challenge: %s, num: %s" % (challenge, num) response = int(CryptoLib.generateKeyHash(str(num)), 16) while response != challenge: num += 1 response = int(CryptoLib.generateKeyHash(str(num)), 16) #print " challenge: %x, hash: %x" % (challenge, response) return num
def challengeResponse(self): # generate a sufficiently large random number num = random.randrange(100000, 1000000) # generate a random number to subtract from it firstFew = random.randrange(1000, 10000) firstFew = num - firstFew # create the challenge hash challenge = CryptoLib.generateKeyHash(str(num)) return num, challenge, firstFew
def handleClientMessages(self, msg, knownClient, addr): if self.DBG is True:print " message received: '%s'" % msg msgContents = msg.split(":") if msgContents[0] == "AUTH": if knownClient is not None: print "client has already been Authenticated, ignore message..." else: self.challengeAnswer, challenge, firstFew = self.challengeResponse() response = str(challenge) + ":" + str(firstFew) self.sendMessage(response, addr) elif msgContents[0] == "CONTRIBUTION": if int(msgContents[1]) == self.challengeAnswer: if self.DBG is True: print "solved challenge!!!" for existingClients in self.clients.values(): if existingClients.get_name() == msgContents[2]: print "client already exists, removing old client..." msg = "DISCONNECTED:" msg = CryptoLib.encyptUsingSymmetricKey(existingClients.get_session_key(), existingClients.get_initialization_vector(), msg) self.sendMessage(msg, existingClients.get_address()) self.clients.pop(existingClients.get_address()) # create and add new client to list client = Client.User(msgContents[2], addr) self.clients[addr] = client #************************************************** # Start authentication procedure (Augmented PDM) #************************************************** clientContribution = msgContents[3] b = CryptoLib.generateRandomKey(16) # retrieve the safe prime for the user primeTag = 'P' + (self.clients[addr]).get_name() try: p = ChatServer.config.getint('SectionTwo', primeTag) except Exception, e: print "couldn't get prime...: ", e self.clients.pop(addr) return # generate server contribution (2^b mod p) to send to server serverContribution = pow(ChatServer.generator, int(b.encode('hex'), 16), p) # retrieve the password hash for the user pwdHashTag = 'W' + (self.clients[addr]).get_name() # 2^W mod p try: pwdHashExp = ChatServer.config.getint('SectionTwo', pwdHashTag) except Exception, e: print "couldn't get pwd hash...: ", e self.clients.pop(addr) return #print "2^W mod p for client, pwdHashTag:%s ==> pwdHashExp:%s" % (pwdHashTag, pwdHashExp) # 2^ab mod p sharedKey1 = CryptoLib.generateSecretKey(int(clientContribution), int(b.encode('hex'), 16), p) # 2^bW mod p sharedKey2 = CryptoLib.generateSecretKey(pwdHashExp, int(b.encode('hex'), 16), p) sessionKey = (str(sharedKey1) + str(sharedKey2))[0:16] #print "Server: sharedKey1: %s, sharedKey2: %s, sessionKey: %s" % (sharedKey1, # sharedKey2, sessionKey) # HASH(2^ab mod p, 2^bW modp) sessionKeyHash = CryptoLib.generateKeyHash(sessionKey) if self.clients.get(addr) is not None: self.clients.get(addr).set_session_key_and_hash(sessionKey, sessionKeyHash) iv = CryptoLib.generateRandomKey(8).encode('hex') self.clients.get(addr).set_initialization_vector(iv) response = str(serverContribution) + ":" + sessionKeyHash + ":" + iv if self.DBG: print "====== sending: ", response self.sendMessage(response, addr) return
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