Ejemplo n.º 1
0
    def clock_sync_protocol(self):
        if len(data) != 1 : return

        # Parse uname and use it to find the shared key
        uname = data[0]
        shared_key = connected_clients[uname]['shared_key']
        shared_iv  = connected_clients[uname]['shared_iv']

        # Create a nonce, encrypt it with the shared key, send it to the client
        nonce1 = Random.new().read( 32 )
        encrypted_nonce1 = common.aes_encrypt(nonce1, shared_key, shared_iv)

        encrypt_msg = common.encode_msg([encrypted_nonce1])
        data = common.send_and_receive(encrypt_msg, self.client_address, self.socket, 1024, 2)

        # Return if nonce doesn't match
        user_nonce1 = base64.b64decode( data[0] )
        if nonce1 != user_nonce1 : return
        encrypted_n2 = base64.b64decode( data[1] )

        # Decrypt the client's nonce
        incr_shared_key = SHA256.new(str( common.increment_key(shared_key) )).digest()
        nonce2 = common.aes_decrypt(encrypted_n2, incr_shared_key, shared_iv)

        # Get the current server timestamp and encrypt it
        timestamp = datetime.datetime.now().strftime(fmt)
        encrypted_timestamp = common.aes_encrypt(timestamp, shared_key, shared_iv)
        final_msg = common.encode_msg([nonce2, encrypted_timestamp])
        self.socket.sendto(final_msg, self.client_address)
Ejemplo n.º 2
0
    def list_protocol(self, data):
        if len(data) != 1 : return

        # Parse uname and use it to find the shared key
        uname = data[0]
        shared_key = connected_clients[uname]['shared_key']
        shared_iv  = connected_clients[uname]['shared_iv']

        # Create a nonce, encrypt it with the shared key, send it to the client
        nonce1 = Random.new().read( 32 )
        encrypted_nonce1 = common.aes_encrypt(nonce1, shared_key, shared_iv)

        encrypt_msg = common.encode_msg([encrypted_nonce1])
        data = common.send_and_receive(encrypt_msg, self.client_address, self.socket, 1024, 2)

        # Return if the nonce doesn't match
        user_nonce1 = base64.b64decode( data[0] )
        if nonce1 != user_nonce1 : return
        encrypted_n2 = base64.b64decode( data[1] )

        # Decrypt the client's nonce
        incr_shared_key = SHA256.new(str( common.increment_key(shared_key) )).digest()
        nonce2 = common.aes_decrypt(encrypted_n2, incr_shared_key, shared_iv)

        # Build the list of connected clients
        client_list = ''
        for key, value in connected_clients.iteritems():
            client_list += key + ','

        # Encrypt the list and send it to the client (along with the decrypted nonce)
        encrypted_client_list = common.aes_encrypt(client_list, shared_key, shared_iv)
        final_msg = common.encode_msg([nonce2, encrypted_client_list])
        self.socket.sendto(final_msg, self.client_address)
Ejemplo n.º 3
0
    def sync_clocks(self):
        # Send the "SYNC" server request
        self.sock.sendto("SYNC", self.server_address)

        # Receive the dos cookie
        dos_cookie = self.sock.recv(1024)

        # Send the dos cookie back, along with the username
        msg = "SYNC," + dos_cookie + "," + self.username
        self.sock.sendto(msg, (HOST, PORT))

        # Receive an encrypted nonce and decrypt it
        encrypted_nonce = self.sock.recv(1024)
        decoded_encrypted_nonce = base64.b64decode(encrypted_nonce)
        decrypted_nonce = common.aes_decrypt(decoded_encrypted_nonce, self.shared_key, self.shared_iv)

        # Create a new nonce and encrypt with the shared key + 1
        nonce2 = Random.new().read( 32 )
        incr_shared_key = SHA256.new(str( common.increment_key(self.shared_key) )).digest()
        encrypted_nonce2 = common.aes_encrypt(nonce2, incr_shared_key, self.shared_iv)

        # Send the decrypted nonce and encrypted second nonce to the server
        send_msg = common.encode_msg([decrypted_nonce, encrypted_nonce2])
        data = common.send_and_receive(send_msg, self.server_address, self.sock, 8192, 2)

        # Check the nonce
        serv_nonce2 = base64.b64decode( data[0] )
        if serv_nonce2 != nonce2 : return
        encrypted_timestamp = base64.b64decode(data[1])

        # Decrypt the timestamp
        timestamp_str = common.aes_decrypt(encrypted_timestamp, self.shared_key, self.shared_iv)
        timestamp = ''
        try:
            timestamp = datetime.datetime.strptime(timestamp_str, fmt)
        except ValueError:
            print "timestamp import issue"
            return

        # Not sure if this legal, please check it!!!
        time_offset = datetime.datetime.now() - timestamp
Ejemplo n.º 4
0
    def get_client_list(self):
        # Send the "LIST" server request
        self.sock.sendto("LIST", self.server_address)

        # Receive the dos cookie
        dos_cookie = self.sock.recv(1024)

        # Send the dos cookie back, along with the username
        msg = "LIST," + dos_cookie + "," + self.username
        self.sock.sendto(msg, (HOST, PORT))

        # Receive an encrypted nonce and decrypt it
        encrypted_nonce = self.sock.recv(1024)
        decoded_encrypted_nonce = base64.b64decode(encrypted_nonce)
        decrypted_nonce = common.aes_decrypt(decoded_encrypted_nonce, self.shared_key, self.shared_iv)

        # Create a new nonce and encrypt with the shared key + 1
        nonce2 = Random.new().read( 32 )
        incr_shared_key = SHA256.new(str( common.increment_key(self.shared_key) )).digest()
        encrypted_nonce2 = common.aes_encrypt(nonce2, incr_shared_key, self.shared_iv)

        # Send the decrypted nonce and encrypted second nonce to the server
        #send_msg = encoded_decrypted_nonce + "," + encrypted_nonce2
        send_msg = common.encode_msg([decrypted_nonce, encrypted_nonce2])
        data = common.send_and_receive(send_msg, self.server_address, self.sock, 8192, 2)

        # Check the nonce
        serv_nonce2 = base64.b64decode( data[0] )
        if serv_nonce2 != nonce2 : return
        encrypted_unames = base64.b64decode(data[1])

        # Decrypt and print names
        unames = common.aes_decrypt(encrypted_unames, self.shared_key, self.shared_iv)
        unames = unames.split(',')
        for name in unames:
            print name
Ejemplo n.º 5
0
    def ticket_protocol(self, data):
        if len(data) != 2 : return

        # Parse uname and use it to find the shared key
        uname = data[0]
        shared_key = connected_clients[uname]['shared_key']
        shared_iv  = connected_clients[uname]['shared_iv']

        # Decrypt the requested user and timestamp
        msg = common.aes_decrypt(base64.b64decode(data[1]), shared_key, shared_iv).split(",",2)
        if len(msg) != 2 : return

        requested_user      = msg[0]
        requested_user_ip   = connected_clients[requested_user]['ip']
        requested_user_port = str(connected_clients[requested_user]['port'])
        user_timestamp_str  = ''
        user_timestamp      = ''
        try:
            user_timestamp_str = msg[1]
            user_timestamp     = datetime.datetime.strptime(msg[1], fmt)
        except ValueError:
            print "timestamp import issue"
            return

        # Verify timestamp is within acceptable range
        if common.verify_timestamp(user_timestamp, 5):
            # Lookup public key requested_user and create shared key
            requested_user_pub_key_str = self.get_user_pub_key(requested_user).exportKey()
            shared_user_key = self.create_shared_key()

            # Create ticket to requested_user
            encrypted_keys, ciphertext = self.create_ticket(requested_user, uname, shared_user_key)

            # Encrypt response with the shared key + 1
            encrypt_msg = user_timestamp_str + ',' + requested_user + ',' + shared_user_key + ',' + encrypted_keys + ',' + \
                          ciphertext + ',' + requested_user_pub_key_str + ',' + requested_user_ip + ',' + requested_user_port
            incr_shared_key = SHA256.new(str( common.increment_key(shared_key) )).digest()
            encrypted_msg   = common.aes_encrypt(encrypt_msg, incr_shared_key, shared_iv)

            # Encode the response (with ticket) and send it to the client
            final_msg = common.encode_msg([encrypted_msg])
            self.socket.sendto(final_msg, self.client_address)

        else:
            print "Timestamp not current enough"
            return
Ejemplo n.º 6
0
    def logout(self):
        try:
            self.sock.sendto("LOGOUT", self.server_address)
            dos_cookie = self.sock.recv(1024)

            # Compute current timestamp and encrypt
            timestamp           = datetime.datetime.now().strftime(fmt)
            encrypted_timestamp = common.aes_encrypt(timestamp, self.shared_key, self.shared_iv)

            # Sign the message
            iv            = Random.new().read( 16 )
            signature_msg = SHA256.new(str(iv))
            signature     = common.sign(signature_msg, self.priv_key)

            # Send logout request
            send_msg_body = common.encode_msg([self.username, iv, signature, encrypted_timestamp])
            send_msg      = 'LOGOUT' + ',' + dos_cookie + ',' + send_msg_body
            data = common.send_and_receive(send_msg, self.server_address, self.sock, 2048, 3)
            if len(data) != 3 :
                return None
            decode_data = common.decode_msg(data)

            iv2              = decode_data[0]
            serv_signature   = decode_data[1]
            encrypted_status = decode_data[2]

            # Verify server signature
            h = SHA256.new(str(iv2))
            verifier = PKCS1_v1_5.new(server_pub_key)

            if verifier.verify(h, str(serv_signature)):
                # Decrypt status
                status = common.aes_decrypt(encrypted_status, self.shared_key, self.shared_iv)

                if status == "LOGOUTSUCCESS":
                    print "Logout successful!"
                    sys.exit()
                else:
                    print "Logout failed"
            else:
                print "Logout failed - invalid signature"

            return
        except socket.timeout as e:
            print "Server is not responding"
            sys.exit()
Ejemplo n.º 7
0
    def login_to_server(self, password):
        try:
            self.sock.sendto("LOGIN", self.server_address)
            dos_cookie = self.sock.recv(1024)

            # compute diffie hellman value and encrypt with password hash
            iv1         = Random.new().read( 16 )
            dh          = diffie_hellman.DiffieHellman()
            dh_key      = str(dh.genPublicKey())
            dh_val      = common.aes_encrypt(dh_key, password, iv1)

            # Sign the message
            signature_msg = SHA256.new(str(self.username) + str(iv1))
            signature     = common.sign(signature_msg, self.priv_key)

            # Encrypt plaintext using server public key
            encrypt_msg = common.encode_msg([self.username, iv1, signature, dh_val])
            encrypted_keys, ciphertext = common.public_key_encrypt(encrypt_msg, server_pub_key)

            send_msg = "LOGIN," + dos_cookie + "," + encrypted_keys + "," + ciphertext
            self.sock.settimeout(3)
            data = common.send_and_receive(send_msg, self.server_address, self.sock, 8192, 2)
            if len(data) != 2 : return None

            rec_msg = common.public_key_decrypt(data[0], data[1], self.priv_key)
            decoded_msg = common.decode_msg(rec_msg)
            iv2                   = decoded_msg[0]
            signature             = decoded_msg[1]
            encrypted_serv_dh_val = decoded_msg[2]
            nonce1                = decoded_msg[3]

            # Verify the signature
            h = SHA256.new(str(iv2))
            verifier = PKCS1_v1_5.new(server_pub_key)

            if verifier.verify(h, str(signature)):
                # Decrypt server dh val
                server_dh_val = long(common.aes_decrypt(encrypted_serv_dh_val, password, iv2))

                # Generate shared key
                dh.genKey(server_dh_val)
                shared_key = dh.getKey()

                # Encrypt nonce1 with our shared key
                nonce2         = Random.new().read( 32 )
                iv3            = Random.new().read( 16 )
                encrypted_n1   = common.aes_encrypt(nonce1, shared_key, iv3)

                # Encrypt mesage with pub key of the server
                encrypt_msg = common.encode_msg([iv3, encrypted_n1, nonce2])
                encrypted_keys, ciphertext = common.public_key_encrypt(encrypt_msg, server_pub_key)

                # Send message
                send_msg = encrypted_keys + ',' + ciphertext
                data = common.send_and_receive(send_msg, self.server_address, self.sock, 4096, 2)
                if len(data) != 2 : return None

                rec_msg               = common.public_key_decrypt(data[0], data[1], self.priv_key)
                decoded_msg           = common.decode_msg(rec_msg)
                iv4                   = decoded_msg[0]
                encrypted_serv_nonce2 = decoded_msg[1]

                # Verify user nonce1 value matches the value we sent
                serv_nonce2 = common.aes_decrypt(encrypted_serv_nonce2, shared_key, iv4)

                if nonce2 == serv_nonce2:
                    self.shared_key = shared_key
                    self.shared_iv  = iv4
                    print "Successfully logged in!"
                else:
                    self.shared_key = None
                    print "Login unsuccessful"
                    sys.exit()
            else:
                print "Server could not be verified"
                sys.exit()

        except socket.timeout as e:
            print "Server is not responding"
            sys.exit()
Ejemplo n.º 8
0
    def handle_request(self, data, addr):
        data = data.split(',', 4)

        if data[0] == 'AUTH':
            if len(data) != 3 : return
            # Decrypt message with our private key and break out message
            msg                 = common.public_key_decrypt(data[1], data[2], self.priv_key)
            decoded_msg         = common.decode_msg(msg)
            connected_uname     = decoded_msg[0]
            encr_ticket_key     = decoded_msg[1]
            encr_ticket_ciphert = decoded_msg[2]
            iv2                 = decoded_msg[3]
            signature           = decoded_msg[4]
            encrypted_nonce     = decoded_msg[5]

            # Decrypt ticket
            ticket = common.public_key_decrypt(encr_ticket_key, encr_ticket_ciphert, self.priv_key)
            ticket = common.decode_msg(ticket)
            if len(ticket) != 6 : return
            iv                          = ticket[0]
            serv_signature              = ticket[1]
            shared_user_key             = ticket[2]
            requesting_user             = ticket[3]
            requesting_user_pub_key_str = ticket[4]
            expiration_datetime_str     = ticket[5]

            # Verify ticket is not expired and username from ticket matches requesting username
            expiration_timestamp = ''
            try:
                expiration_timestamp = datetime.datetime.strptime(expiration_datetime_str, fmt)
            except ValueError:
                return
            # Check offset!!!
            if common.is_timestamp_current(expiration_timestamp + time_offset) != True : return
            if requesting_user != connected_uname: return

            # Verify server's signature
            h = SHA256.new(str(iv))
            verifier = PKCS1_v1_5.new(server_pub_key)

            if verifier.verify(h, str(serv_signature)):
                # Now verify signature of initiating user
                requesting_user_pub_key = RSA.importKey(requesting_user_pub_key_str)
                h = SHA256.new(str(iv2))
                verifier = PKCS1_v1_5.new(requesting_user_pub_key)

                if verifier.verify(h, str(signature)):
                    # Create signature
                    iv3 = Random.new().read( 16 )
                    signature_msg = SHA256.new(str(iv3))
                    signature     = common.sign(signature_msg, self.priv_key)

                    # Add user to authenticated users
                    self.authenticated_users[requesting_user]['shared_key'] = shared_user_key
                    self.authenticated_users[requesting_user]['shared_iv']  = iv3
                    self.authenticated_users[requesting_user]['sequence_n'] = int(iv3.encode('hex'), 16)
                    self.authenticated_users[requesting_user]['address']  = addr

                    # Now decrypt nonce, and encrypt back with kab + 1
                    nonce = common.aes_decrypt(encrypted_nonce, shared_user_key, iv2)
                    incr_shared_key = SHA256.new(str( common.increment_key(shared_user_key) )).digest()
                    our_encrypted_nonce = common.aes_encrypt(nonce, incr_shared_key, iv3)

                    # Send final message back to initiating user, encrypted with their pub key
                    encrypt_msg = common.encode_msg([iv3, signature, our_encrypted_nonce])
                    encrypted_keys, ciphertext = common.public_key_encrypt(encrypt_msg, requesting_user_pub_key)
                    send_msg = encrypted_keys + "," + ciphertext
                    self.sock.sendto(send_msg, addr)

            else:
                return

            return
        if data[0] == 'MESSAGE':
            if len(data) != 4 : return
            decoded_msg   = common.decode_msg(data[1:])
            if len(decoded_msg) != 3 : return
            connected_uname = decoded_msg[0]
            user_hmac_key   = decoded_msg[1]
            encrypted_msg   = decoded_msg[2]

            # Retrieve session info for user
            if self.authenticated_users.get(connected_uname) == None : return
            shared_key = self.authenticated_users[connected_uname]['shared_key']
            shared_iv  = self.authenticated_users[connected_uname]['shared_iv']
            user_addr  = self.authenticated_users[connected_uname]['address']
            self.authenticated_users[connected_uname]['sequence_n'] += 1
            sequence_n = self.authenticated_users[connected_uname]['sequence_n']

            # Decrypt message
            msg = common.aes_decrypt(encrypted_msg, shared_key, shared_iv).split(',',1)
            if len(msg) != 2 : return
            user_seq_n = msg[0]
            user_msg   = msg[1]

            # Verify sequence number matches our sequence number
            if user_seq_n != str(sequence_n) : return

            # Verify hmac key
            hmac_key = hmac.new(shared_key, str(user_seq_n) + ',' + user_msg).digest()
            if user_hmac_key != hmac_key : return

            print connected_uname + ': ' + user_msg
            return

        else:
            return
Ejemplo n.º 9
0
    def get_ticket_from_server(self, user):
        try:
            self.sock.sendto("TICKET", self.server_address)
            dos_cookie = self.sock.recv(1024)

            # Request to talk to given user, sending current timestamp
            # Please not sure if adding the offset here is legal, please check!!!
            timestamp             = (datetime.datetime.now() + time_offset).strftime(fmt)
            msg                   = user + "," + timestamp
            encrypted_msg         = common.aes_encrypt(msg, self.shared_key, self.shared_iv)
            encoded_encrypted_msg = common.encode_msg([encrypted_msg])

            # Send request to server
            send_msg = "TICKET," + dos_cookie + ',' + self.username + ',' + encoded_encrypted_msg
            self.sock.settimeout(5)
            data = common.send_and_receive(send_msg, self.server_address, self.sock, 16384, 1)
            if len(data) != 1 : return

            # Decrypt the message with shared key + 1
            msg = base64.b64decode( data[0] )
            incr_shared_key = SHA256.new(str( common.increment_key(self.shared_key) )).digest()
            msg = common.aes_decrypt(msg, incr_shared_key, self.shared_iv).split(',', 8)
            if len(msg) != 8 : return

            serv_timestamp       = msg[0]
            serv_user_to_talk_to = msg[1]
            shared_key_ab        = msg[2]
            encr_ticket_key      = msg[3]
            encr_ticket_ciphert  = msg[4]
            user_pk              = msg[5]
            user_ip              = msg[6]
            user_port            = msg[7]

            # Not sure what to do with timestamp offset here!!!
            if serv_timestamp == timestamp and serv_user_to_talk_to == user:
                nonce         = Random.new().read( 32 )
                iv2           = Random.new().read( 16 )
                signature_msg = SHA256.new(str(iv2))
                signature     = common.sign(signature_msg, self.priv_key)

                # Encrypt nonce with our shared key
                encrypted_nonce = common.aes_encrypt(nonce, shared_key_ab, iv2)

                # Encrypt mesage with pub key of the user
                user_pk = RSA.importKey(user_pk)
                encrypt_msg = common.encode_msg([self.username, encr_ticket_key, encr_ticket_ciphert, iv2, signature, encrypted_nonce])
                encrypted_keys, ciphertext = common.public_key_encrypt(encrypt_msg, user_pk)

                user_address = (user_ip,int(user_port))
                send_msg = "AUTH" + ',' + encrypted_keys + ',' + ciphertext
                data = common.send_and_receive(send_msg, user_address, self.sock, 2048, 2)
                if len(data) != 2 : return

                # Decrypt message with our private key and break out message
                msg                 = common.public_key_decrypt(data[0], data[1], self.priv_key)
                decoded_msg         = common.decode_msg(msg)
                iv3             = decoded_msg[0]
                signature       = decoded_msg[1]
                encrypted_nonce = decoded_msg[2]

                # Decrypt nonce with shared key + 1
                incr_shared_key = SHA256.new(str( common.increment_key(shared_key_ab) )).digest()
                connected_nonce = common.aes_decrypt(encrypted_nonce, incr_shared_key, iv3)

                # Verify nonce is correct
                if connected_nonce == nonce:
                    self.authenticated_users[serv_user_to_talk_to]['shared_key'] = shared_key_ab
                    self.authenticated_users[serv_user_to_talk_to]['shared_iv']  = iv3
                    self.authenticated_users[serv_user_to_talk_to]['sequence_n'] = int(iv3.encode('hex'), 16)
                    self.authenticated_users[serv_user_to_talk_to]['address']    = user_address

                return

        except socket.timeout as e:
            print "Server is not responding"
            sys.exit()
Ejemplo n.º 10
0
    def login_protocol(self, data):
        if len(data) != 2 : return

        # Decrypt message with our private key and break out message
        msg              = common.public_key_decrypt(data[0], data[1], server_priv_key)
        decoded_msg      = common.decode_msg(msg)
        uname            = decoded_msg[0]
        iv1              = decoded_msg[1]
        signature        = decoded_msg[2]
        encrypted_dh_val = decoded_msg[3]

        if connected_clients.get(uname) is not None: return

        # Lookup public key of the user
        user_pub_key = self.get_user_pub_key(uname)

        # Verify the user's signature
        h = SHA256.new(str(uname) + str(iv1))
        verifier = PKCS1_v1_5.new(user_pub_key)

        if verifier.verify(h, str(signature)):
            print "Signature Verified!"
            pass_hash = base64.b64decode( self.get_password_hash(uname) )

            # Decrypt DH val
            diff_hell_val = long(common.aes_decrypt(encrypted_dh_val, pass_hash, iv1))

            # Create random values
            nonce1         = Random.new().read( 32 )
            iv2            = Random.new().read( 16 )

            # Compute our diffie hellman value and encrypt with password hash
            dh = diffie_hellman.DiffieHellman()
            serv_dh_key = str(dh.genPublicKey())
            serv_dh = common.aes_encrypt(serv_dh_key, pass_hash, iv2)

            # Establish shared key
            dh.genKey(diff_hell_val)
            shared_key = dh.getKey()

            # Sign the message
            signature_msg = SHA256.new(str(iv2))
            signature     = common.sign(signature_msg, server_priv_key )

            # Encrypt with public key of user
            encrypt_msg = common.encode_msg([iv2, signature, serv_dh, nonce1])
            encrypted_server_keys, ciphertext = common.public_key_encrypt(encrypt_msg, user_pub_key)

            # Send message
            send_msg = encrypted_server_keys + "," + ciphertext
            data = common.send_and_receive(send_msg, self.client_address, self.socket, 1024, 2)
            if len(data) != 2 : return

            rec_msg               = common.public_key_decrypt(data[0], data[1], server_priv_key)
            decoded_msg           = common.decode_msg(rec_msg)
            iv3                   = decoded_msg[0]
            encrypted_user_nonce1 = decoded_msg[1]
            nonce2                = decoded_msg[2]

            # Verify user encrypted nonce1 with the shared key
            user_nonce1 = common.aes_decrypt(encrypted_user_nonce1, shared_key, iv3)

            if nonce1 == user_nonce1:
                print "Login Sucess for user: "******"Login Failure for user: "******"The signature is not authentic"
            return