Beispiel #1
0
    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
Beispiel #2
0
 def create_token(self, user1_address, user2_address, user1_key, user2_key, key):
     token1 = user1_address + ":" + user1_key
     token2 = user2_address + ":" + user2_key
     token = token1 + "," + token2
     # TODO: server needs to store the client information into the clients dictionary (maybe key on username?)
     token = CryptoLib.encyptUsingSymmetricKey(key, self.clients[user1_address].getInitializationVector(), token)
     self.sendMessage(token, user1_address)
Beispiel #3
0
 def list_of_clients(self):
     print "Get list of clients from server"
     msg = "list:"
     msg = CryptoLib.encyptUsingSymmetricKey(self.sessionKey, self.sessionID, msg)
     self.send_message(msg,self.serverAddr, self.port)
     print
     response = self.receive_response()
     if response is not None:
         response = CryptoLib.decryptUsingSymetricKey(self.sessionKey, self.sessionID, response)
     print "list of clients: ", response
Beispiel #4
0
 def send_encrypted_message(self, msg):
     """
     Sends encrypted message through socket
     :param msg: message to be sent
     :return: True/False
     """
     ret = False
     try:
         msg = CryptoLib.encyptUsingSymmetricKey(self.sessionKey, self.sessionID, msg)
         self.sock.sendto(msg, (self.serverAddr, self.port))
         ret = True
     except Exception, e:
         print "send message failed: ", e
Beispiel #5
0
    def receive_peer_messages(self):
        """
        Reads messages from socket
        :return: data read
        """
        try:
            msg, addr = self.sock.recvfrom(ChatClient.MSG_LEN)
            if self.peers.has_key(addr):
                peer = self.peers.get(addr)
                response = CryptoLib.decryptUsingSymetricKey(peer.get_shared_key(),
                                                             peer.get_initialization_vector(), msg)
                response = response.split(":")
                if response[0] == "PEER_CONTRIBUTION":
                    peer_contribution = response[1]
                    if response[2] is None:
                        print "Error: didn't receive IV"
                    else:
                        peer.set_initialization_vector(response[2])
                        shared_key = pow(peer_contribution, peer.get_client_b(), self.peerPrime)
                        peer.set_shared_key(shared_key)
                        challenge = CryptoLib.generateRandomKey(16)
                        msg = CryptoLib.encyptUsingSymmetricKey(peer.get_shared_key(),
                                                                peer.get_initialization_vector(), challenge)
                        self.send_message(msg, peer.get_address()[0], peer.get_address()[1])
                else:
                    print "Error: unknown message sent!!!"
            elif addr == (self.serverAddr, self.port):
                response = CryptoLib.decryptUsingSymetricKey(self.sessionKey, self.sessionID, msg)
                response = response.split(":")
                if response[0] == "DISCONNECTED":
                    print " Server Disconnected us... Good bye!"
                    sys.exit(0)

        except socket.timeout, e:
            #print "Thread Error: ", e
            msg = None
Beispiel #6
0
    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
Beispiel #7
0
                # 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
            else:
                print "Invalid client!!!"

        elif msgContents[0] == "DISCONNECTING":
            msg = "DISCONNECTED:"
            msg = CryptoLib.encyptUsingSymmetricKey(self.clients[addr].get_session_key(),
                                                    self.clients[addr].get_initialization_vector(), msg)
            self.sendMessage(msg, addr)
            self.clients.pop(addr)

        elif msgContents[0] == "VALIDATE":
            if knownClient is not None and knownClient.get_session_key_hash() == msgContents[1]:
                knownClient.set_public_key(msgContents[3])
                msgContents[2] = int(msgContents[2]) +1
                response = "ACKNOWLEDGE:" + str(msgContents[2])
                response = CryptoLib.encyptUsingSymmetricKey(knownClient.get_session_key(),
                                                             knownClient.get_initialization_vector(),
                                                             response)
                self.sendMessage(response, knownClient.get_address())
                # client is fully authenticated
                knownClient.set_authenticated = True
            else:
Beispiel #8
0
    def authenticate_peer(self, username):
        ret = False
        # choose a random iv

        # send server the username of the client we want to chat with
        msg = "CONP:" + username

        # step 1: Request Server for the tickets
        msg = CryptoLib.encyptUsingSymmetricKey(self.sessionKey, self.sessionID, msg)
        if not self.send_message(msg, self.serverAddr, self.port):
            return ret

        # Step 2: receive the combined ticket from the server and split it into two parts
        combined_ticket = self.receive_response()
        combined_ticket = CryptoLib.decryptUsingSymetricKey(self.sessionKey, self.sessionID, combined_ticket)
        if combined_ticket == "unknown client requested":
            print combined_ticket
            return False
        combined_ticket = combined_ticket.split(",")
        if combined_ticket is None:
            print "Error!!! Didn't receive ticket from server"
            return ret

        combined_ticket = CryptoLib.decryptUsingSymetricKey(self.sessionKey, self.sessionID,
                                                            combined_ticket).split(",")
        user_ticket = combined_ticket[0]
        peer_ticket = combined_ticket[1]

        # decrypt the token for this client and unpack it.
        # Each ticket should contain the address, port and public key of the client concat using ,'s
        user_ticket = CryptoLib.decryptUsingSymetricKey(self.sessionKey, self.sessionID, user_ticket)
        user_ticket = user_ticket.split(":")
        peer_address = user_ticket[0]
        peer_tmp_shared_key = user_ticket[1]
        if user_ticket[2] != username:
            print "Error!!! wrong peer received!!!"
            return ret

        peer_tmp_iv = user_ticket[3]

        # create peer object
        peer = Peer.Peer(username, peer_address)

        # Step 3: message to talk to peer encrypted with key given by the server
        # message to peer contains peer's ticket
        msg = "REQUEST_PEER_CONNECTION:" + self.username + ":" + peer_ticket
        msg = CryptoLib.encyptUsingSymmetricKey(peer_tmp_shared_key, peer_tmp_iv, msg)
        if not self.send_message(msg, peer_address[0], peer_address[1]):
            return ret

        # Step 4: Receive peer's contribution for DH key
        response = self.receive_response()
        if response is None:
            print "Error!!! Didn't receive contribution from peer: ", username
            return ret
        peer_contribution = CryptoLib.decryptUsingSymetricKey(peer_tmp_shared_key, peer_tmp_iv, response)

        # Step 5: Generate and send contribution for DH key as well as the initialization vector
        a = CryptoLib.generateRandomKey(32)
        peer_session_id = CryptoLib.generateRandomKey(16)
        client_contribution = pow(self.peerGenerator, a, self.peerPrime)
        msg = "PEER_CONTRIBUTION:" + str(client_contribution) + ":" + peer_session_id
        msg = CryptoLib.encyptUsingSymmetricKey(peer_tmp_shared_key, peer_tmp_iv, msg)
        if not self.send_message(msg, peer_address[0], peer_address[1]):
            return ret

        # Now construct the shared key and set iv and shared key to peer object
        shared_key = pow(peer_contribution, a, self.peerPrime)

        # Step 6: Challenge response (Two way authentication) - user receives challenge, user 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 = self.receive_response()
        if challenge is None:
            print "Error!!! Didn't receive challenge from peer"
            return ret
        challenge = int(CryptoLib.decryptUsingSymetricKey(shared_key, peer_session_id, challenge))
        challenge += 1

        msg = "PEER_CHALLENGE:" + challenge
        msg = CryptoLib.encyptUsingSymmetricKey(shared_key, peer_session_id, msg)
        if not self.send_message(msg, peer_address[0], peer_address[1]):
            return ret

        response = self.receive_response()
        if response is None:
            print "Error!!! Didn't receive response from peer"
            return ret
        response = CryptoLib.decryptUsingSymetricKey(shared_key, peer_session_id, response)

        # If authentication is successful, add the peer to list of connected peers
        if response == challenge + 1:
            peer.set_initialization_vector(peer_session_id)
            peer.set_shared_key(shared_key)
            peer.set_authenticated_flag(True)
            self.peers[username] = peer
            return True

        return False
Beispiel #9
0
    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