def __init__(self):
        self.rsa = RSAClass()
        #generate the Public Private key pair for this client
        self.public_key, self.private_key = self.rsa.generate_keys()

        # read in the Public key of the Server from XML File
        self.pubKey = chilkat.CkPublicKey()
        self.pubKey.LoadXmlFile("Serverpublickey.xml")
        self.ServerPublicKey = self.pubKey.getXml()

        #objects for hashing and diffie hellman
        self.md5_crypt = chilkat.CkCrypt2()
        self.hashcrypt = chilkat.CkCrypt2()
        self.dhAlice = chilkat.CkDh()
        self.md5_crypt.put_EncodingMode("hex")
        #  Set the hash algorithm:
        self.md5_crypt.put_HashAlgorithm("md5")

        self.hashcrypt.put_EncodingMode("hex")
        self.hashcrypt.put_HashAlgorithm("md5")
        # Unlock components above
        self.UnlockComponents()

        #create a oscket and connect to the server
        self.client = socket(AF_INET, SOCK_STREAM)
        self.client.connect(ADDR)

        # setup an AES object with cipher block chaining, 128-bit key, padding size and format
        self.a = AESClass("cbc", 128, 0, "hex")

        # source port of Client for use in communications later
        self.client_src_port = self.client.getsockname()[1]
    def __init__(self, address=('localhost', 0)):
        asyncore.dispatcher.__init__(self)
        #import the Servers Keys, Saved to XML in FileSystem
        privkey = chilkat.CkPrivateKey()
        privkey.LoadXmlFile("Serverprivatekey.xml")
        self.ServerPrivateKey = privkey.getXml()

        #create RSA object
        self.rsa = RSAClass()

        #Chilkat object forCreating hashes
        self.hashcrypt = chilkat.CkCrypt2()
        success = self.hashcrypt.UnlockComponent("T12302015Crypt_sHyDCAFgIR1v")
        if (success != True):
            print(hself.ashcrypt.lastErrorText())
            sys.exit()
        # setting encoding mode for hashing algorithm
        self.hashcrypt.put_EncodingMode("hex")
        self.hashcrypt.put_HashAlgorithm("md5")

        # setup data for Diffie Hellman Key exchange
        self.dhBob = chilkat.CkDh()
        success = self.dhBob.UnlockComponent("T12302015Diffie_eegQ20BTIR5q")
        if (success != True):
            print(self.dhBob.lastErrorText())
            sys.exit()
        self.dhBob.UseKnownPrime(2)
        self.p = self.dhBob.p()
        self.g = self.dhBob.get_G()
        self.eBob = self.dhBob.createE(256)


        #initially set the the AES object with cipher block chaining 128bit
        self.aesObj = AESClass("cbc",128,0,"hex")
        self.inital_setup = "0"
        #store client IDS and nonces
        # nonces used in replay protection
        self.CLIENT_ID_STORE ={}
        self.CLIENT_ID = []

        #placeholders fo the keys (session and shared the same really)
        self.sharedKey = None
        self.sessionkey = None

        # self.set_reuse_addr()
        #bind to socket and listen
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(address)
        #print ("Address Server", address)
        # accept with no backlog
        # syncore dispatcher handles it all
        self.listen(1)
        #store connected clients in LIST
        self.remote_clients = []
    def __init__(self):
        self.rsa = RSAClass()
        #generate the Public Private key pair for this client
        self.public_key, self.private_key = self.rsa.generate_keys()

        # read in the Public key of the Server from XML File
        self.pubKey = chilkat.CkPublicKey()
        self.pubKey.LoadXmlFile("Serverpublickey.xml")
        self.ServerPublicKey = self.pubKey.getXml()

        #objects for hashing and diffie hellman
        self.md5_crypt = chilkat.CkCrypt2()
        self.hashcrypt = chilkat.CkCrypt2()
        self.dhAlice = chilkat.CkDh()
        self.md5_crypt.put_EncodingMode("hex")
        #  Set the hash algorithm:
        self.md5_crypt.put_HashAlgorithm("md5")

        self.hashcrypt.put_EncodingMode("hex")
        self.hashcrypt.put_HashAlgorithm("md5")
        # Unlock components above
        self.UnlockComponents()

        #create a oscket and connect to the server
        self.client = socket(AF_INET, SOCK_STREAM)
        self.client.connect(ADDR)

        # setup an AES object with cipher block chaining, 128-bit key, padding size and format
        self.a = AESClass("cbc",128,0,"hex")

        # source port of Client for use in communications later
        self.client_src_port = self.client.getsockname()[1]
    def run(self):
        #extract the path and private flag from shared memory
        file_path = self.sharedMem["file_path"]
        private = self.sharedMem["private"]

        #AES MODE
        if self.mode == 1:
            #SOCKET create, connect, and send a white space left justified string
            s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            s.connect(('localhost', self.dst_port))
            paddedFile_path = file_path.ljust(1024)
            print "len padded file path ", paddedFile_path
            s.send(paddedFile_path)
            #open file for sending
            file_f = open(file_path, "rb")
            #block transfer
            block = file_f.read(1024)
            #get file size
            filesize = int(os.stat(file_path).st_size)
            #count blocks
            blockCounter = len(block)
            while (block):
                #calc percentage
                calc = (float(blockCounter)/float(filesize))*float(100)
                print calc
                #convert binary the HEX STRING
                hexblock=binascii.hexlify(block)
                #Encypt the Hex String
                block = self.aes.enc_str(hexblock)
                #send block
                s.send(block)
                #read another for the file
                block = file_f.read(1024)
                #add to the counter
                blockCounter += len(block)
            print "file sent"
            #close file
            file_f.close()
            print "AES FILETRANSFER COMPLETE"
            wx.CallAfter(self.text_send.AppendText, "\n" + t() + "AES FILETRANSFER COMPLETE" + "\n")
            s.close()

        #RSA MODE - same as above but with RSA and Private mode
        if self.mode == 2:
            rsa = RSAClass()
            s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            s.connect(('localhost', self.dst_port))

            #receive the public key for encryption
            FSPUBLIC = s.recv(243)
            #if private mode
            if private == True:
                #send this flag to P2P Read Thread of the target client
                s.send("1")
                #private message extract shared mem
                privatemessage = self.sharedMem["privatemessage"]
                enc_private_message = rsa.encrypt_text(str(privatemessage), FSPUBLIC)
                enc_private_message = enc_private_message.ljust(2048)
                s.send(enc_private_message)
                wx.CallAfter(self.text_send.AppendText, "\n" + t() + "RSA privatemessage COMPLETE" + "\n")
                #set private to off
                self.sharedMem["private"] = False
            else:
				s.send("0")
				paddedFile_path = file_path.ljust(1024)
				print "len padded file path ", paddedFile_path
				s.send(paddedFile_path)
	            #get the total size of file in bytes
				filesize = int(os.stat(file_path).st_size)
				file_f = open(file_path, "rb")
				block = file_f.read(1024)
				blockCounter = len(block)

                #same as prior
				while (block):
					calc = (float(blockCounter)/float(filesize))*float(100)
					print calc
					hexblock=binascii.hexlify(block)
					block = rsa.encrypt_text(hexblock, FSPUBLIC)
					s.send(block)
					block = file_f.read(1024)
					blockCounter += len(block)
				file_f.close()
				s.close()
	            # s.send(self.data)
				print "RSA FILETRANSFER COMPLETE"
				wx.CallAfter(self.text_send.AppendText, "\n" + t() + "RSA FILETRANSFER COMPLETE" + "\n")

    # terminate the thread
	def stop(self):
		print "Trying to stop thread "
		if self.process is not None:
			self.process.terminate()
			self.process = None
    def run(self):
        print "size of public_key", len(str(self.public_key))
        # create a new socket and Bind to a Random free port (0)
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.bind(('localhost', 0))
        #get the address and store so it can be returned
        newSocketAddress = s.getsockname()
        self.newReadSocketAddress = newSocketAddress

        import math
        suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
        def human_size(nbytes):
            rank = int((math.log10(nbytes)) / 3)
            rank = min(rank, len(suffixes) - 1)
            human = nbytes / (1024.0 ** rank)
            f = ('%.2f' % human).rstrip('0').rstrip('.')
            return '%s %s' % (f, suffixes[rank])

        # if the mode is AES
        if self.mode == 1:
            #Wait to accept one client
            s.listen(1)
            print "@@@@@@@@@@@@@@@@@@@@@@@@-SECOND SOCKET CREATED AES-@@@@@@@@@@@@@@@@@@@@@@"
            self.socket = s
            # accept the client as a new socket sock
            sock, addr = self.socket.accept()
            #receive the original file path, padded with white space t0 1024 characters
            self.original_file_path = sock.recv(1024)
            #strip the whitespace padding
            unpaddedOriginal = self.original_file_path.strip()
            print "unpaddedOriginal", unpaddedOriginal, len(unpaddedOriginal)
            #split the path and name, then rename with "_txCopy"
            path, filename_ext = os.path.split(unpaddedOriginal)
            filename, extension = os.path.splitext(filename_ext)
            filename = filename + "_txCopy" + extension


            file_f = open(filename,'wb') #open in binary
            block = sock.recv(2752)
            blockCounter = len(block)
            while (block):
                    print "RECIEVED", human_size(blockCounter)
                    block=self.aes.dec_str(block)
                    unhexblock=binascii.unhexlify(block)
                    file_f.write(unhexblock)
                    block=sock.recv(2752)
                    blockCounter += len(block)
            wx.CallAfter(self.text_send.AppendText, "\n" + t() + "AES FILETRANSFER RECIEVED" + "\n")
            print "!!!!!!!!!!!!!!!!!!  FILETRANSFER COMPLETED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
            file_f.close()
            sock.close()
            print "@@@@@@@@@@@@@@@@@@@@@@@ new socket closed @@@@@@@@@@@@@@@@@@@@@@@@@@@@"


        # The same as above but with RSA
        if self.mode == 2:
            s.listen(1)
            print "@@@@@@@@@@@@@@@@@@@@@@@@-SECOND SOCKET CREATED RSA-@@@@@@@@@@@@@@@@@@@@@@"
            self.socket = s
            sock, addr = self.socket.accept()
            #Send This clients Public key to the calling client
            sock.send(self.public_key)
            rsa = RSAClass()

            #receive if this is private message mode
            private = sock.recv(1)
            if private == "1":
				print "ENTERING PRIAVTE MODE"
				privatemessage = sock.recv(2048)
				privatemessage = privatemessage.strip()
				privatemessage = rsa.decrypt_text(privatemessage, self.private_key)
                #append the private received message to the chat window
				wx.CallAfter(self.text_send.AppendText, "\n" + t() + "RSA_PRIVATE:"+privatemessage  + "\n")
            else:
				self.original_file_path = sock.recv(1024)
	            # print "self.original_file_path", self.original_file_path, len(self.original_file_path)
				unpaddedOriginal = self.original_file_path.strip()
				print "unpaddedOriginal", unpaddedOriginal, len(unpaddedOriginal)
				path, filename_ext = os.path.split(unpaddedOriginal)
				filename, extension = os.path.splitext(filename_ext)
				filename = filename + "_txCopy" + extension
				file_f = open(filename,'wb')
	            # data = sock.recv(1024)
				block=sock.recv(4608)
	            #----receiving & decrypting-------
				blockCounter = len(block)
				while (block):
					print "RECIEVED ", human_size(blockCounter)
					block = rsa.decrypt_text(block, self.private_key)
					unhexblock=binascii.unhexlify(block)
					file_f.write(unhexblock)
					block=sock.recv(4608)
					blockCounter += len(block)
				wx.CallAfter(self.text_send.AppendText, "\n" + t() + "RSA FILETRANSFER RECIEVED" + "\n")
				print "!!!!!!!!!!!!!!!!!!  FILETRANSFER COMPLETED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
				file_f.close()
				sock.close()
				print "@@@@@@@@@@@@@@@@@@@@@@@ new socket closed @@@@@@@@@@@@@@@@@@@@@@@@@@@@"
class Client:
    """Class for a user of the chat client."""
    def __init__(self):
        self.rsa = RSAClass()
        #generate the Public Private key pair for this client
        self.public_key, self.private_key = self.rsa.generate_keys()

        # read in the Public key of the Server from XML File
        self.pubKey = chilkat.CkPublicKey()
        self.pubKey.LoadXmlFile("Serverpublickey.xml")
        self.ServerPublicKey = self.pubKey.getXml()

        #objects for hashing and diffie hellman
        self.md5_crypt = chilkat.CkCrypt2()
        self.hashcrypt = chilkat.CkCrypt2()
        self.dhAlice = chilkat.CkDh()
        self.md5_crypt.put_EncodingMode("hex")
        #  Set the hash algorithm:
        self.md5_crypt.put_HashAlgorithm("md5")

        self.hashcrypt.put_EncodingMode("hex")
        self.hashcrypt.put_HashAlgorithm("md5")
        # Unlock components above
        self.UnlockComponents()

        #create a oscket and connect to the server
        self.client = socket(AF_INET, SOCK_STREAM)
        self.client.connect(ADDR)

        # setup an AES object with cipher block chaining, 128-bit key, padding size and format
        self.a = AESClass("cbc", 128, 0, "hex")

        # source port of Client for use in communications later
        self.client_src_port = self.client.getsockname()[1]

    def UnlockComponents(self):
        success = self.md5_crypt.UnlockComponent("T12302015Crypt_sHyDCAFgIR1v")
        if (success != True):
            print(self.md4_crypt.lastErrorText())
            sys.exit()

        success = self.hashcrypt.UnlockComponent("T12302015Crypt_sHyDCAFgIR1v")
        if (success != True):
            print(self.hashcrypt.lastErrorText())
            sys.exit()

        success = self.dhAlice.UnlockComponent("T12302015Diffie_eegQ20BTIR5q")
        if (success != True):
            print(self.dhAlice.lastErrorText())
            sys.exit()

    def setUpClient(self):

        #random nonce generated for the cient
        # seeded (probally with system time) to ensure new nonce generation
        # well as much as pseudorandom can ensure
        random.seed()
        nonce = random.randrange(10000000000000, 99999999999999)

        # generate an ID dictionary for the client, passing its
        # public-key and nonce to the server
        # serializing the object
        # hashing it + concatenating the hash to ther serialized data
        # then encypting with the servers public to ensure the nonce
        # cannot be intercepted
        # send to server
        firstID = {'nonce': nonce, 'public_key': self.public_key}
        pid = pickle.dumps(firstID)
        hashStr = self.md5_crypt.hashStringENC(str(nonce))
        finalID = pid + hashStr
        encyptedpayload = self.rsa.encrypt_text(finalID, self.ServerPublicKey)
        self.client.send(encyptedpayload)

        # recieve the Responce from the server with orginal client nonce
        # and the servers nonce
        challange_Resp = self.client.recv(1024)
        # decypt with the clients public key
        challange_Resp = self.rsa.decrypt_text(challange_Resp,
                                               self.private_key)
        # decypt with the servers private - verifys - because nonces will be mangled
        # if there a different private RSA used - It is assumed server only has this key
        challange_Resp = self.rsa.decrypt_with_public(challange_Resp,
                                                      self.ServerPublicKey)
        # remove the Hash of the orginal serialized object - 32 Characters from end of message
        h = challange_Resp[-32:]
        # remove the serialized object - to the last 32 characters of the data
        challange_Resp = challange_Resp[:-32]
        # rehash this object
        h2 = self.md5_crypt.hashStringENC(challange_Resp)
        # de-serialized the object back to a python dictionary
        challange_Resp = pickle.loads(challange_Resp)

        # extract the returned nonce-1, check if valid, close socket and exit if not
        nonce_1 = challange_Resp["cnonce"]
        if h == h2 and nonce == nonce_1:
            print "\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
            print "Challange Integrity Verified"
            print "$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"
        else:
            print "Integrity Challange Failed - closing connection"
            client.close()
            sys.exit(0)

        # extract the server nonce
        snonce = challange_Resp["snonce"]

        #check to see if a "Master Client" has setup the CHatroom
        #if not then initate the Diffie-Hellman Key exchange with the server
        # if it has happened retieve the Session-key from the server

        # have to have exact bytes(sync issues) !!!!!!!!!!!!!!!!!!!!
        inital_setup = self.client.recv(1)
        print "inital_setup has occured before = ", inital_setup
        serverKey = None
        if inital_setup == "1":
            print "attempt to recv server key"
            serverKey = self.client.recv(1280)
            serverKey = self.rsa.decrypt_text(serverKey, self.private_key)
            serverKey = self.rsa.decrypt_with_public(serverKey,
                                                     self.ServerPublicKey)
            h = serverKey[-32:]
            serverKey = serverKey[:-32]
            h2 = self.md5_crypt.hashStringENC(serverKey)
            serverKey = pickle.loads(serverKey)

            if h == h2 and serverKey["cnonce"] == nonce and serverKey[
                    "snonce"] == snonce:
                sk = serverKey["aes_key"]
                print "serverSessionKey", sk
                print "setting serverSessionKey"
                self.a.set_sessionkey(sk)
                iv = self.a.getCrypt().hashStringENC(sk)
                self.a.setIv(iv)
            else:
                print "Integrity Mismatch"
                client.close()
                sys.exit(0)

        # Recieved "Pickled" object on socket - ie serialised to String
        # Deserialize Data recieved back into
        # Python dictionary then remove the objects
        else:
            try:
                pk1 = self.client.recv(1792)
                pk2 = self.client.recv(1792)
                pk1 = self.rsa.decrypt_text(pk1, self.private_key)
                pk2 = self.rsa.decrypt_text(pk2, self.private_key)
                defragment = pk2 + pk1
                defragment = self.rsa.decrypt_with_public(
                    defragment, self.ServerPublicKey)
                h = defragment[-32:]
                defragment = defragment[:-32]
                h2 = self.md5_crypt.hashStringENC(defragment)
                dictObj = pickle.loads(defragment)

                if h == h2 and dictObj["cnonce"] == nonce and dictObj[
                        "snonce"] == snonce:
                    p = dictObj["p"]
                    g = dictObj["g"]
                    g = int(g)
                    eBob = dictObj["e"]
                else:
                    print "Integrity Mismatch"
                    client.close()
                    sys.exit(0)

            except:
                print "fails to recieve Diffie-hellman data"
                sys.exit(0)

            # use the information for Diffie-hellman cleint side
            success = self.dhAlice.SetPG(p, g)
            if (success != True):
                print("P is not a safe prime")
                sys.exit()

            eAlice = self.dhAlice.createE(256)
            eAlice = self.rsa.encrypt_text(eAlice, self.ServerPublicKey)
            print "size of eAlice", len(str(eAlice))
            self.client.send(eAlice)

            #Alice's shared secret
            kAlice = self.dhAlice.findK(eBob)
            print("Alice's shared secret (should be equal to Bob's)")
            print(kAlice)

            sessionkey = self.hashcrypt.hashStringENC(kAlice)
            print "SessionKey", sessionkey
            self.a.set_sessionkey(sessionkey)
            iv = self.a.getCrypt().hashStringENC(sessionkey)
            self.a.setIv(iv)

        # print "serverKey testing"
        # print type(serverKey)
        # print len(str(serverKey))
        # depending on if this is a first setup or not
        # use the key (ie same key)for AES ---- one that is sent in open
        # would have to use a digital envelope of the like to achieve this properly

        # setup this sides AES object
        self.a.setupAES()

        print "-------------AES KEY-----------------"
        print self.a.get_key()
    def run(self):
        #extract the path and private flag from shared memory
        file_path = self.sharedMem["file_path"]
        private = self.sharedMem["private"]

        #AES MODE
        if self.mode == 1:
            #SOCKET create, connect, and send a white space left justified string
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect(('localhost', self.dst_port))
            paddedFile_path = file_path.ljust(1024)
            print "len padded file path ", paddedFile_path
            s.send(paddedFile_path)
            #open file for sending
            file_f = open(file_path, "rb")
            #block transfer
            block = file_f.read(1024)
            #get file size
            filesize = int(os.stat(file_path).st_size)
            #count blocks
            blockCounter = len(block)
            while (block):
                #calc percentage
                calc = (float(blockCounter) / float(filesize)) * float(100)
                print calc
                #convert binary the HEX STRING
                hexblock = binascii.hexlify(block)
                #Encypt the Hex String
                block = self.aes.enc_str(hexblock)
                #send block
                s.send(block)
                #read another for the file
                block = file_f.read(1024)
                #add to the counter
                blockCounter += len(block)
            print "file sent"
            #close file
            file_f.close()
            print "AES FILETRANSFER COMPLETE"
            wx.CallAfter(self.text_send.AppendText,
                         "\n" + t() + "AES FILETRANSFER COMPLETE" + "\n")
            s.close()

        #RSA MODE - same as above but with RSA and Private mode
        if self.mode == 2:
            rsa = RSAClass()
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect(('localhost', self.dst_port))

            #receive the public key for encryption
            FSPUBLIC = s.recv(243)
            #if private mode
            if private == True:
                #send this flag to P2P Read Thread of the target client
                s.send("1")
                #private message extract shared mem
                privatemessage = self.sharedMem["privatemessage"]
                enc_private_message = rsa.encrypt_text(str(privatemessage),
                                                       FSPUBLIC)
                enc_private_message = enc_private_message.ljust(2048)
                s.send(enc_private_message)
                wx.CallAfter(self.text_send.AppendText,
                             "\n" + t() + "RSA privatemessage COMPLETE" + "\n")
                #set private to off
                self.sharedMem["private"] = False
            else:
                s.send("0")
                paddedFile_path = file_path.ljust(1024)
                print "len padded file path ", paddedFile_path
                s.send(paddedFile_path)
                #get the total size of file in bytes
                filesize = int(os.stat(file_path).st_size)
                file_f = open(file_path, "rb")
                block = file_f.read(1024)
                blockCounter = len(block)

                #same as prior
                while (block):
                    calc = (float(blockCounter) / float(filesize)) * float(100)
                    print calc
                    hexblock = binascii.hexlify(block)
                    block = rsa.encrypt_text(hexblock, FSPUBLIC)
                    s.send(block)
                    block = file_f.read(1024)
                    blockCounter += len(block)
                file_f.close()
                s.close()
                # s.send(self.data)
                print "RSA FILETRANSFER COMPLETE"
                wx.CallAfter(self.text_send.AppendText,
                             "\n" + t() + "RSA FILETRANSFER COMPLETE" + "\n")

    # terminate the thread

        def stop(self):
            print "Trying to stop thread "
            if self.process is not None:
                self.process.terminate()
                self.process = None
    def run(self):
        print "size of public_key", len(str(self.public_key))
        # create a new socket and Bind to a Random free port (0)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('localhost', 0))
        #get the address and store so it can be returned
        newSocketAddress = s.getsockname()
        self.newReadSocketAddress = newSocketAddress

        import math
        suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']

        def human_size(nbytes):
            rank = int((math.log10(nbytes)) / 3)
            rank = min(rank, len(suffixes) - 1)
            human = nbytes / (1024.0**rank)
            f = ('%.2f' % human).rstrip('0').rstrip('.')
            return '%s %s' % (f, suffixes[rank])

        # if the mode is AES
        if self.mode == 1:
            #Wait to accept one client
            s.listen(1)
            print "@@@@@@@@@@@@@@@@@@@@@@@@-SECOND SOCKET CREATED AES-@@@@@@@@@@@@@@@@@@@@@@"
            self.socket = s
            # accept the client as a new socket sock
            sock, addr = self.socket.accept()
            #receive the original file path, padded with white space t0 1024 characters
            self.original_file_path = sock.recv(1024)
            #strip the whitespace padding
            unpaddedOriginal = self.original_file_path.strip()
            print "unpaddedOriginal", unpaddedOriginal, len(unpaddedOriginal)
            #split the path and name, then rename with "_txCopy"
            path, filename_ext = os.path.split(unpaddedOriginal)
            filename, extension = os.path.splitext(filename_ext)
            filename = filename + "_txCopy" + extension

            file_f = open(filename, 'wb')  #open in binary
            block = sock.recv(2752)
            blockCounter = len(block)
            while (block):
                print "RECIEVED", human_size(blockCounter)
                block = self.aes.dec_str(block)
                unhexblock = binascii.unhexlify(block)
                file_f.write(unhexblock)
                block = sock.recv(2752)
                blockCounter += len(block)
            wx.CallAfter(self.text_send.AppendText,
                         "\n" + t() + "AES FILETRANSFER RECIEVED" + "\n")
            print "!!!!!!!!!!!!!!!!!!  FILETRANSFER COMPLETED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
            file_f.close()
            sock.close()
            print "@@@@@@@@@@@@@@@@@@@@@@@ new socket closed @@@@@@@@@@@@@@@@@@@@@@@@@@@@"

        # The same as above but with RSA
        if self.mode == 2:
            s.listen(1)
            print "@@@@@@@@@@@@@@@@@@@@@@@@-SECOND SOCKET CREATED RSA-@@@@@@@@@@@@@@@@@@@@@@"
            self.socket = s
            sock, addr = self.socket.accept()
            #Send This clients Public key to the calling client
            sock.send(self.public_key)
            rsa = RSAClass()

            #receive if this is private message mode
            private = sock.recv(1)
            if private == "1":
                print "ENTERING PRIAVTE MODE"
                privatemessage = sock.recv(2048)
                privatemessage = privatemessage.strip()
                privatemessage = rsa.decrypt_text(privatemessage,
                                                  self.private_key)
                #append the private received message to the chat window
                wx.CallAfter(
                    self.text_send.AppendText,
                    "\n" + t() + "RSA_PRIVATE:" + privatemessage + "\n")
            else:
                self.original_file_path = sock.recv(1024)
                # print "self.original_file_path", self.original_file_path, len(self.original_file_path)
                unpaddedOriginal = self.original_file_path.strip()
                print "unpaddedOriginal", unpaddedOriginal, len(
                    unpaddedOriginal)
                path, filename_ext = os.path.split(unpaddedOriginal)
                filename, extension = os.path.splitext(filename_ext)
                filename = filename + "_txCopy" + extension
                file_f = open(filename, 'wb')
                # data = sock.recv(1024)
                block = sock.recv(4608)
                #----receiving & decrypting-------
                blockCounter = len(block)
                while (block):
                    print "RECIEVED ", human_size(blockCounter)
                    block = rsa.decrypt_text(block, self.private_key)
                    unhexblock = binascii.unhexlify(block)
                    file_f.write(unhexblock)
                    block = sock.recv(4608)
                    blockCounter += len(block)
                wx.CallAfter(self.text_send.AppendText,
                             "\n" + t() + "RSA FILETRANSFER RECIEVED" + "\n")
                print "!!!!!!!!!!!!!!!!!!  FILETRANSFER COMPLETED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
                file_f.close()
                sock.close()
                print "@@@@@@@@@@@@@@@@@@@@@@@ new socket closed @@@@@@@@@@@@@@@@@@@@@@@@@@@@"
class Client:
    """Class for a user of the chat client."""
    def __init__(self):
        self.rsa = RSAClass()
        #generate the Public Private key pair for this client
        self.public_key, self.private_key = self.rsa.generate_keys()

        # read in the Public key of the Server from XML File
        self.pubKey = chilkat.CkPublicKey()
        self.pubKey.LoadXmlFile("Serverpublickey.xml")
        self.ServerPublicKey = self.pubKey.getXml()

        #objects for hashing and diffie hellman
        self.md5_crypt = chilkat.CkCrypt2()
        self.hashcrypt = chilkat.CkCrypt2()
        self.dhAlice = chilkat.CkDh()
        self.md5_crypt.put_EncodingMode("hex")
        #  Set the hash algorithm:
        self.md5_crypt.put_HashAlgorithm("md5")

        self.hashcrypt.put_EncodingMode("hex")
        self.hashcrypt.put_HashAlgorithm("md5")
        # Unlock components above
        self.UnlockComponents()

        #create a oscket and connect to the server
        self.client = socket(AF_INET, SOCK_STREAM)
        self.client.connect(ADDR)

        # setup an AES object with cipher block chaining, 128-bit key, padding size and format
        self.a = AESClass("cbc",128,0,"hex")

        # source port of Client for use in communications later
        self.client_src_port = self.client.getsockname()[1]


    def UnlockComponents(self):
        success = self.md5_crypt.UnlockComponent("T12302015Crypt_sHyDCAFgIR1v")
        if (success != True):
            print(self.md4_crypt.lastErrorText())
            sys.exit()

        success = self.hashcrypt.UnlockComponent("T12302015Crypt_sHyDCAFgIR1v")
        if (success != True):
            print(self.hashcrypt.lastErrorText())
            sys.exit()

        success = self.dhAlice.UnlockComponent("T12302015Diffie_eegQ20BTIR5q")
        if (success != True):
            print(self.dhAlice.lastErrorText())
            sys.exit()


    def setUpClient(self):

        #random nonce generated for the cient
        # seeded (probally with system time) to ensure new nonce generation
        # well as much as pseudorandom can ensure
        random.seed()
        nonce = random.randrange(10000000000000,99999999999999)

        # generate an ID dictionary for the client, passing its
        # public-key and nonce to the server
        # serializing the object
        # hashing it + concatenating the hash to ther serialized data
        # then encypting with the servers public to ensure the nonce
        # cannot be intercepted
        # send to server
        firstID = {'nonce' : nonce, 'public_key': self.public_key}
        pid = pickle.dumps(firstID)
        hashStr = self.md5_crypt.hashStringENC(str(nonce))
        finalID = pid + hashStr
        encyptedpayload = self.rsa.encrypt_text(finalID, self.ServerPublicKey)
        self.client.send(encyptedpayload)

        # recieve the Responce from the server with orginal client nonce
        # and the servers nonce
        challange_Resp = self.client.recv(1024)
        # decypt with the clients public key
        challange_Resp = self.rsa.decrypt_text(challange_Resp,self.private_key)
        # decypt with the servers private - verifys - because nonces will be mangled
        # if there a different private RSA used - It is assumed server only has this key
        challange_Resp = self.rsa.decrypt_with_public(challange_Resp, self.ServerPublicKey)
        # remove the Hash of the orginal serialized object - 32 Characters from end of message
        h = challange_Resp[-32:]
        # remove the serialized object - to the last 32 characters of the data
        challange_Resp = challange_Resp[:-32]
        # rehash this object
        h2 = self.md5_crypt.hashStringENC(challange_Resp)
        # de-serialized the object back to a python dictionary
        challange_Resp = pickle.loads(challange_Resp)


        # extract the returned nonce-1, check if valid, close socket and exit if not
        nonce_1 = challange_Resp["cnonce"]
        if h == h2 and nonce == nonce_1:
            print "\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
            print "Challange Integrity Verified"
            print "$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"
        else:
            print "Integrity Challange Failed - closing connection"
            client.close()
            sys.exit(0)

        # extract the server nonce
        snonce = challange_Resp["snonce"]


        #check to see if a "Master Client" has setup the CHatroom
        #if not then initate the Diffie-Hellman Key exchange with the server
        # if it has happened retieve the Session-key from the server

        # have to have exact bytes(sync issues) !!!!!!!!!!!!!!!!!!!!
        inital_setup = self.client.recv(1)
        print "inital_setup has occured before = ", inital_setup
        serverKey = None
        if inital_setup == "1":
            print "attempt to recv server key"
            serverKey = self.client.recv(1280)
            serverKey = self.rsa.decrypt_text(serverKey, self.private_key)
            serverKey = self.rsa.decrypt_with_public(serverKey, self.ServerPublicKey)
            h = serverKey[-32:]
            serverKey = serverKey[:-32]
            h2 = self.md5_crypt.hashStringENC(serverKey)
            serverKey = pickle.loads(serverKey)

            if h == h2 and serverKey["cnonce"] == nonce and serverKey["snonce"] == snonce:
                sk  = serverKey["aes_key"]
                print "serverSessionKey", sk
                print "setting serverSessionKey"
                self.a.set_sessionkey(sk)
                iv = self.a.getCrypt().hashStringENC(sk)
                self.a.setIv(iv)
            else:
                print "Integrity Mismatch"
                client.close()
                sys.exit(0)



        # Recieved "Pickled" object on socket - ie serialised to String
        # Deserialize Data recieved back into
        # Python dictionary then remove the objects
        else:
            try:
                pk1 = self.client.recv(1792)
                pk2 = self.client.recv(1792)
                pk1 = self.rsa.decrypt_text(pk1, self.private_key)
                pk2 = self.rsa.decrypt_text(pk2, self.private_key)
                defragment = pk2 + pk1
                defragment = self.rsa.decrypt_with_public(defragment, self.ServerPublicKey)
                h = defragment[-32:]
                defragment = defragment[:-32]
                h2 = self.md5_crypt.hashStringENC(defragment)
                dictObj = pickle.loads(defragment)

                if h == h2 and dictObj["cnonce"] == nonce and dictObj["snonce"] == snonce:
                    p = dictObj["p"]
                    g = dictObj["g"]
                    g = int(g)
                    eBob = dictObj["e"]
                else:
                    print "Integrity Mismatch"
                    client.close()
                    sys.exit(0)

            except:
                print "fails to recieve Diffie-hellman data"
                sys.exit(0)

            # use the information for Diffie-hellman cleint side
            success = self.dhAlice.SetPG(p,g)
            if (success != True):
                print("P is not a safe prime")
                sys.exit()


            eAlice = self.dhAlice.createE(256)
            eAlice = self.rsa.encrypt_text(eAlice, self.ServerPublicKey)
            print "size of eAlice", len(str(eAlice))
            self.client.send(eAlice)

            #Alice's shared secret
            kAlice = self.dhAlice.findK(eBob)
            print("Alice's shared secret (should be equal to Bob's)")
            print(kAlice)

            sessionkey = self.hashcrypt.hashStringENC(kAlice)
            print "SessionKey", sessionkey
            self.a.set_sessionkey(sessionkey)
            iv = self.a.getCrypt().hashStringENC(sessionkey)
            self.a.setIv(iv)

        # print "serverKey testing"
        # print type(serverKey)
        # print len(str(serverKey))
        # depending on if this is a first setup or not
        # use the key (ie same key)for AES ---- one that is sent in open
        # would have to use a digital envelope of the like to achieve this properly

        # setup this sides AES object
        self.a.setupAES()

        print "-------------AES KEY-----------------"
        print self.a.get_key()
class Chatroom(asyncore.dispatcher):
        #asyncore dispatcher listening on local-host random socket
    def __init__(self, address=('localhost', 0)):
        asyncore.dispatcher.__init__(self)
        #import the Servers Keys, Saved to XML in FileSystem
        privkey = chilkat.CkPrivateKey()
        privkey.LoadXmlFile("Serverprivatekey.xml")
        self.ServerPrivateKey = privkey.getXml()

        #create RSA object
        self.rsa = RSAClass()

        #Chilkat object forCreating hashes
        self.hashcrypt = chilkat.CkCrypt2()
        success = self.hashcrypt.UnlockComponent("T12302015Crypt_sHyDCAFgIR1v")
        if (success != True):
            print(hself.ashcrypt.lastErrorText())
            sys.exit()
        # setting encoding mode for hashing algorithm
        self.hashcrypt.put_EncodingMode("hex")
        self.hashcrypt.put_HashAlgorithm("md5")

        # setup data for Diffie Hellman Key exchange
        self.dhBob = chilkat.CkDh()
        success = self.dhBob.UnlockComponent("T12302015Diffie_eegQ20BTIR5q")
        if (success != True):
            print(self.dhBob.lastErrorText())
            sys.exit()
        self.dhBob.UseKnownPrime(2)
        self.p = self.dhBob.p()
        self.g = self.dhBob.get_G()
        self.eBob = self.dhBob.createE(256)


        #initially set the the AES object with cipher block chaining 128bit
        self.aesObj = AESClass("cbc",128,0,"hex")
        self.inital_setup = "0"
        #store client IDS and nonces
        # nonces used in replay protection
        self.CLIENT_ID_STORE ={}
        self.CLIENT_ID = []

        #placeholders fo the keys (session and shared the same really)
        self.sharedKey = None
        self.sessionkey = None

        # self.set_reuse_addr()
        #bind to socket and listen
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(address)
        #print ("Address Server", address)
        # accept with no backlog
        # syncore dispatcher handles it all
        self.listen(1)
        #store connected clients in LIST
        self.remote_clients = []

    #Authentication Protocol Steps occur here
    #Diffy Hellman, key exchange 
    #digital signing of messages
    #hashes included in messages 
    #confidential provided by the clients public key that was 
    #transmitted to the server on its initial connection in the accept handler 
    #when the challenge response occurred
    #the nonces, socket, keys, source address and public keys are passed to this method
    def auth(self, client, address, cpub, snonce, cnonce):
        #send if  this setup has happened already with an initial client
        #because the session key was already generated
        #doing otherwise would create different keys!

        #send the flag to the connected client 
        #so they can comply with protocol
        client.send(self.inital_setup)
        #if this has already happened then send the client
        # the symmetric key in a digital envelope using the Public key they submitted 
        if self.inital_setup == "1":
            print 'Setup for new client', address
            print ">>>>>>>>>>>>>>>>>>>>>>>Sending Session Key>>>>>>>>>>>>>>>>>"
            print ">>>>>>>>>>>>>>>>>>>>>>>Digital Envelope>>>>>>>>>>>>>>>>>>>>>\n"
            #create a dictionary of data
            dictobj = {'aes_key':self.aesObj.get_key(),"snonce":snonce, "cnonce":cnonce}
            #serialize it
            pickledump = pickle.dumps(dictobj)
            #!!!!!HASH!!!!! it
            h = self.hashcrypt.hashStringENC(pickledump)
            #concatenate the hash to the serialized data
            pickledump = pickledump + h
            #encrypt with the server !!!!!PRIVATE KEY!! for !!!!DIGTIAL SIGNATURE!!
            sk = self.rsa.encrypt_with_private(pickledump, self.ServerPrivateKey)
            #encrypt with the clients Public key for !!!!!!CONFIDENTIALITY!!!!!!!!
            sk = self.rsa.encrypt_text(sk, cpub)
            # send it back to the client
            client.send(sk)
        else:
            print 'Setup for first client', address
            # serialize objects with dictionary and "pickle"
            #these are the data requirement for the client to complete the 
            # !!!!!-----diffie hellman-----!!!! mathematical process
            dictobj = {'p' : self.p, 'g' : self.g,"e" : self.eBob, "snonce":snonce, "cnonce":cnonce}
            pickdump = pickle.dumps(dictobj)
            #hash serialized data, concatenate and encrypt with the Private key Server for
            #!!!!!Digital Signature!!!!
            h = self.hashcrypt.hashStringENC(pickdump)
            pickdump = pickdump + h
            pickdump = self.rsa.encrypt_with_private(pickdump, self.ServerPrivateKey)

            #Have the split the data and encypt each half separately with the
            #clients public key 
            # Data was exceeding the MODULUS Size used for the RSA Object
            pk1 = self.rsa.encrypt_text(pickdump[-768:], cpub)
            pk2 = self.rsa.encrypt_text(pickdump[:-768], cpub)
            #Send the FRAGMENTED packet to the client for reassembly
            client.send(pk1)
            client.send(pk2)

            ## without this loop will get a resource unavailable
            # error crashing the server ---- wait till receive
            loop = True
            while loop:
                try:
                    #receive the clients "shared value", generated for the Public
                    #Diffie Hellman components sent to from the server
                    eAlice = client.recv(768)
                    try:
                        #decrypt the message with the servers Private key
                        #Confidentiality 
                        #(unnecessary!!!!!!!! as this is public data ---  but added anyway)
                        eAlice = self.rsa.decrypt_text(eAlice, self.ServerPrivateKey)
                    except:
                        "nothinf"
                    loop = False
                except:
                	"do nothing"

            # using the information from Client
            kBob = self.dhBob.findK(eAlice)

            #generate the MUTUALLY GENERATED SHARED SECRET

            self.sharedKey = kBob
            print "Shared Secret information"
            print(address, "shared secret (should be equal to Bob's)")
            print self.sharedKey

            # Use a hashing algorithm to generate 128 bit Session key
            self.sessionkey = self.hashcrypt.hashStringENC(kBob)

            print ""   #Console Outputs (testing)
            print "-----------Session-key---------------"
            print "------------generated---------------"
            print self.sessionkey
            print "-----------------------------------"
            # Use custom AES object
            # if the setup hes not happen already then
            # use the current new session key
            # and setup the AES object

            if self.inital_setup == "0":
                # iv is MD5 hash of session key
                iv = self.aesObj.getCrypt().hashStringENC(self.sessionkey)
                self.aesObj.setIv(iv)
                self.aesObj.set_sessionkey(self.sessionkey)
                self.aesObj.setupAES()

            # first time setup has occurred 
            self.inital_setup = "1"
        return True

    # socket accept event handler of Asyncore dispatcher
    # used to accept new Clients connections in a Synchronous manner then after 
    # challenge response and protocol wrap them in a approximation of Asynchronous behavior
    # with Asyncore Dispatcher which will poll each at timed intervals
    def handle_accept(self):

        # Accept event handler on listening socket
        # Accept a new client then start the Protocol Process
        socket, addr = self.accept()
        if (socket == None):
            return
        print 'Accepted client from port ', addr

        sleep(0.1)

        # remove the client identifier
        ID = socket.recv(1024)
        #decrypt with the server Private-key
        client_ID = self.rsa.decrypt_text(ID, self.ServerPrivateKey)
        #extract and generate hash
        orginal_hash = client_ID[-32:]
        #de-concatenate the clients ID
        client_ID = client_ID[:-32]

        print "***********************"
        print "***********************"

        dictObj = pickle.loads(client_ID)
        # clients nonce value
        cnonce = dictObj["nonce"]
        #Generate a comparison HASH value
        testhash  = self.hashcrypt.hashStringENC(str(cnonce))

        ###Should disconnect them here if this Check fails
        if orginal_hash == testhash:
            print "\nNONCE Integrity Validated\n"

        # extract the Clients RSA public key
        cpub = dictObj["public_key"]
        #store their  nonce
        self.CLIENT_ID_STORE[addr] = cnonce

        #SERVER generate a random nonce 
        random.seed()
        snonce = random.randrange(10000000000000,99999999999999)

        #response the the client with clients nonce and Servers nonce
        responce =  {"snonce":snonce, "cnonce": cnonce}
        #serialize the dictionary
        responce = pickle.dumps(responce)
        #hash it for INTEGRITY
        h = self.hashcrypt.hashStringENC(str(responce))
        #concatenate the hash to serialized data
        responce = responce + h
        # encrypt with the Servers Private key for DIGITAL SIGNATURE
        responce = self.rsa.encrypt_with_private(responce, self.ServerPrivateKey)
        # Encrypt with the clients public key for Confidentiality
        responce = self.rsa.encrypt_text(responce, cpub)
        #send message
        socket.send(responce)


        #Replay Protection (If a client nonce has occurred Before then dont add them 
        # to the Ayncore Wrapper Chat Room)
        # This would have to be save to a local Database to be really useful
        # as all nonces as lost once the server is down
        allowed = True
        if self.inital_setup == "1":
            print "previous nonces"
            for c in list(self.CLIENT_ID):
                print c[1]
                if c[1] == cnonce and snonce == c[2]:
                    print "AUTH already occurred for ", c[0]
                    #set allowed to false
                    #they wont get added to the system
                    allowed = False

        if allowed == True:
            client_id_list =[ (cpub), (cnonce), (snonce)]
            self.CLIENT_ID.append(client_id_list)
            # If setup protocol returns true
            # add remote socket to room
            stat = self.auth(socket, addr, cpub, snonce, cnonce)
            if stat == True:
                self.remote_clients.append(RemoteClient(self, socket, addr))

    #Handle Read
    #Called when the asynchronous loop detects that a read
    #call on the channels socket will succeed.
    def handle_read(self):
        self.read()

    def broadcast(self, message):

    	# broadcasts messages to all sockets that are connected
    	# to the server - stored in (remote_clients)
    	# filterS the origin socket of the message (does not return the message)
        try:
            orginal_hash = message[-32:]
            # remove the original serialized object from the concatenated
            # hash
            message = message[:-32]
            #hash the extracted object
            test_hash = self.hashcrypt.hashStringENC(message)
            # de-serialize and extract data
            dictObj = pickle.loads(message)

            #get the source port of the message
            src_port = dictObj["src_port"]
            #data
            src_data = dictObj["data"]
            #is this RSA or AES (only used in the PEER TO PEER message exchange)
            mode = dictObj["FTX_ENC"]

            # IF a <list> command (message) is sent then
            # send back a string of connected ports
            remoteConnectedClients = [] 
            if dictObj["list"] == True:
                connlist = "Conn_list "
                for remote_client in self.remote_clients:
                    if remote_client.get_address()[1] == src_port:
                        # ID this port as coming from the client that requested this LIST
                        connlist = connlist + " : " + str(remote_client.get_address()[1]) + " <-You "
                    else:
                        remoteConnectedClients.append(remote_client.get_address()[1])
                        connlist = connlist + " : " + str(remote_client.get_address()[1])
                connlist = self.aesObj.enc_str(connlist)      
                connlist = {"data" : connlist, "src_port": src_port, "FTX_ENC": mode, "remoteConnectedClients": remoteConnectedClients}
                connlist = pickle.dumps(connlist)
                
            packet = {"data" : src_data, "src_port": src_port, "FTX_ENC": mode, "remoteConnectedClients": None}
            src_data = pickle.dumps(packet)

            # Check the Integrity of received data vrs the new hash of extracted obj
            # NOT OVERLY USEFUL WITH STRING MESSAGES
            if test_hash == orginal_hash:
                "Integrity Verified"
            else:
                print "Integrity fail"

            # test Decryption --- (not necessary)
            test =  pickle.loads(src_data)
            dec_message_test = self.aesObj.dec_str(test["data"])
            print "Test Decrypt :", dec_message_test

            #console message
            print "Broadcasting encrypted mess :", test["data"] , " from 127.0.0.1:", src_port

            #loop through all the connected clients 
            for remote_client in self.remote_clients:
                # don't broadcast the message back to source socket
                if not (remote_client.get_address()[1] == src_port) and (dictObj["tx"] == False):
                    remote_client.send(src_data)
                # send back the LIST data to who requested it (connection list)
                if remote_client.get_address()[1] == src_port and dictObj["list"] == True:
                    remote_client.send(connlist)
                #START A PEER TO PEER FILE TRANSFER HANDSHAKE with a Destination Port
                #Choose by the source client
                #this will create 2 new THREADS , with new SOCKETS, to send encrypted files and strings
                #directly from client to client by passing the server
                if remote_client.get_address()[1] == int(dictObj["p2p_port"]) and dictObj["tx"] == True:
                    remote_client.send(src_data)
        except Exception, e:
            print "er Broadcasting"
            print str(e)