from tkinter import *
from tkinter.scrolledtext import ScrolledText
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import binascii
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto import Random
import os


key_size = 1024

def genKeys():
    keyPair = RSA.generate(key_size)

    
    pubKey = keyPair.publickey()

    public_file = keygenwin.entry1.get()
    #print("PF",public_file)
    if(public_file == ''):
        
        keygenwin.ftext.delete('1.0',END) #clear  win
        
        keygenwin.ftext.insert('1.0',"No public key filename entered!\n")
        
        return
    
    file_obj = open(public_file+".pem", "wb") #save public key
    file_obj.write(pubKey.exportKey('OpenSSH'))
    file_obj.close()

    private_file = keygenwin.entry3.get()
    if(private_file == ''):
        keygenwin.ftext.delete('1.0',END) #clear  win
        keygenwin.ftext.insert('1.0',"No private key filename entered!\n")
        return

    file_obj = open(private_file+".pem", "wb") #save private key
    file_obj.write(keyPair.exportKey('PEM'))
    file_obj.close()


    keygenwin.ftext.delete('1.0',END) #clear  win
    keygenwin.ftext.insert('1.0',"Keys Generated, .pem added to filename for security\nBack these up in a secure place\n")

    #print("pubfile",public_file)

    nText=StringVar()
    nText.set(public_file+".pem")  
    keygenwin.entry1.configure(textvariable=nText)

    nText=StringVar()
    nText.set(private_file+".pem")  
    keygenwin.entry3.configure(textvariable=nText)  

def rsa_encryptPW():  #encrypt password using RSA, message using AEC
    #RSA encrypt password

    mypubkey = encptgenwin.entry1.get() #get pubkey filename
    try:
        with open(mypubkey, 'r') as f:
            public_key = RSA.import_key(f.read())
    except:
        encptgenwin.ftext.insert(END,'Bad Public Key filename, Check Ext\n')
        return
    emsg = encptgenwin.entry4.get() #get password to encrypt
    encryptor = PKCS1_OAEP.new(public_key)
    encrypted = encryptor.encrypt(str.encode(emsg))
    filename = encptgenwin.entry3.get() #get password filename
    try:
        file_obj = open(filename, "wb") #save encrypted PW
        file_obj.write(encrypted)
        file_obj.close()
    except:
        encptgenwin.ftext.insert(END,'Bad Password filename, Check Ext\n')
        return
    aec_enccrytpMSG()
    
    #encptgenwin.ftext.delete('1.0',END) #clear enc win
    #encptgenwin.ftext.insert(END,'\n\nEncryption Done')

    #nText=StringVar()
    #nText.set(filename+".pem")  
    #encptgenwin.entry3.configure(textvariable=nText)  

# AEC encrypt message
def aec_enccrytpMSG():
    
    emsg=encptgenwin.ftext.get('1.0',END)   
    if(emsg=='\n'):     #no msg to encrypt
        text='     No Message to Encrypt!'  
        encptgenwin.ftext.insert('1.0',text+"\n")
        return

    chunksize = 64*1024
    outputfile =   encptgenwin.entry2.get() #get file name to save encryption to.
    password =  encptgenwin.entry4.get() # get password
    key = getKey(password)
    
    chunk = bytes(emsg,'utf-8')
    chunk += b' ' * (16 - (len(chunk) % 16))
    filesize = str(len(emsg)).zfill(16)
    IV = Random.new().read(16)

    encryptor = AES.new(key, AES.MODE_CBC, IV)
    filename = encptgenwin.entry2.get() # get filname to save 
    try:
        with open(filename, 'wb') as outfile:
        
            outfile.write(filesize.encode('utf-8'))
            outfile.write(IV)
            outfile.write(encryptor.encrypt(chunk))
            encptgenwin.ftext.insert(END,'\n\nEncryption Done')
    except:
        encptgenwin.ftext.insert(END,'Bad Message filename, Check Ext\n') 
    return

def getKey(password):   # hash password
        hasher = SHA256.new(password.encode('utf-8'))
        return hasher.digest()


#-------------------------decrypt PW--------------------------------
def rsa_decrypt():
    global PassWord

    filename = decptgenwin.entry4.get() #get PW filename
    try:
        with open(filename, 'rb') as f:
            Fencrypted = f.read()
    except:
        decptgenwin.ftext.insert('1.0',"Bad Password Filename, Check Ext\n")
        return
    username= decptgenwin.entry1.get() # get users private key
    try:
        with open(username, 'r') as f:
            private_key = RSA.import_key(f.read())
    except:
        decptgenwin.ftext.insert('1.0',"Bad Private key Filename, Check Ext\n")
        return
    decryptor = PKCS1_OAEP.new(private_key)  #(keyPair)
    try:
        decrypted = decryptor.decrypt(Fencrypted)
    except:
        decptgenwin.ftext.insert('1.0',"Incorrect decryption\n")
        return
    PassWord= decrypted.decode("utf-8")
    #decptgenwin.ftext.delete('1.0',END) #clear dec win
    #decptgenwin.ftext.insert('1.0',asc+"\n") #put decrypted msg in window
    aec_decrypt()
    

#------------------------decrypt MSG--------------------------------
def aec_decrypt():
    global PassWord
    chunksize = 64*1024
    filename = decptgenwin.entry3.get() # get filname to decrypt
    #password =   decryptwin.entry3.get() # get password
    key = getKey(PassWord)
    try:
        with open(filename, 'rb') as infile:
            filesize = int(infile.read(16))
            IV = infile.read(16)
            decryptor = AES.new(key, AES.MODE_CBC, IV)
            data = infile.read(chunksize)
    except:        
        decptgenwin.ftext.insert('1.0',"Bad Message Filename, Check Ext\n")
        return  
            
    decoded = decryptor.decrypt(data)
    decptgenwin.ftext.delete('1.0',END) #clear dec win
    try:     
        decoded = decoded.decode("utf-8") 
    except:
        decptgenwin.ftext.insert('1.0',"Bad Decryption, Check Filenames\n")
        return
        
    decptgenwin.ftext.insert('1.0',decoded+"\n\n")
    return   



#----------------------- switch screen codes -----------------------
def dcrkey(val):
    global encptgenwin,keygenwin,decptgenwin
    encptgenwin.ftext.grid_forget()   
    encptgenwin.grid_forget()
    if val == 'k':
        keygenwin=KeyGen(root)
    elif val =='d':
        decptgenwin=DecryptGen(root)
    

def encdcr(val):
    global keygenwin,encptgenwin,decptgenwin
    keygenwin.ftext.grid_forget()
    keygenwin.grid_forget()
    if val == 'e':
        encptgenwin=EncryptGen(root)
    elif val =='d':
        decptgenwin=DecryptGen(root)

def enckey(val):
    global keygenwin,encptgenwin,decptgenwin
    decptgenwin.ftext.grid_forget()   
    decptgenwin.grid_forget()
    if val == 'k':
        keygenwin=KeyGen(root)
    elif val =='e':
        encptgenwin=EncryptGen(root)
#---------------------end switch screens ----------------------

class KeyGen(Frame): #Keys window
    
    
    def __init__(self,master):
        Frame.__init__(self,master,bg="white")
        self.master = master
        #master.title("Make Keys")
        self.Init_Val  = StringVar()
        self.Init_Val.set('0')
        

        self.grid()
        
        self.createWidgets()
         

    def create_menu(self):
        menu = Menu(self.master)
        self.master.config(menu=menu)
        keymenu = Menu(menu)
        menu.add_cascade(label="Menu", menu=keymenu,font=('helevitca','14','bold'),background='aqua')
        #filemenu.add_command(label="Generate Keys", command=lambda:genKeys())
        keymenu.add_command(label="Encrypt Windo", command=lambda:encdcr('e'))
        keymenu.add_command(label="Decrypt Windo", command=lambda:encdcr('d'))
        keymenu.add_separator()
        keymenu.add_command(label="Quit", command=lambda:exit())
        

    def createWidgets(self):
        
#-----------------------------------------Encrypt Win Name ---------------------------------
        self.btn01 = Button(self,text='MAKE KEYS',font=('helevitca','12'),fg='black',bg='lime',relief='raised',bd=3,command=lambda:genKeys())
        self.btn01.grid(row=0,column=0)


#----------------------------------Warning Msg Label-----------------------------------------
        self.label1 = Label(self,text='Warning: This may overwrite your other key pairs',font=('helevitca','14'),bg="#fff")
        self.label1.grid(row=3,column=1)

#----------------------------------Exit Button-----------------------------------------
        self.btn04 = Button(self,text='Exit',font=('helevitca','12'),bg="pink",fg='black',relief='raised',bd=3,command=lambda:exit())
        self.btn04.grid(row=0,column=4)
#----------------------------------Entry Filename-----------------------------------------
        self.label2 = Label(self,text='Public Filename(inc ext)',font=('helevitca','12'),bg="#fff",justify='left')
        self.label2.grid(row=1,column=0)
#----------------------------------Password label-----------------------------------------
        self.label4 = Label(self,text='Private Filename(inc ext)',font=('helevitca','12'),bg="#fff",justify='left')
        self.label4.grid(row=2,column=0)

#--------------------------Public File Name Entry -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry1=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry1.grid(row=1,column=1)

#--------------------------Private File Name Entry -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry3=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry3.grid(row=2,column=1)

#-----------------------------------------
        self.create_menu()  
#------------------------------------------Text win------------------------------------------------
        self.ftext = Text(font=("Helvetica",14,'bold'),width=65,height=5)
        self.ftext.grid(row=3,column=0)
        self.ftext.focus_set()        
#--------------------------------------------------------------------------------------------------


class EncryptGen(Frame): #Encrypt window
    
    
    def __init__(self,master):
        Frame.__init__(self,master,bg="white")
        self.master = master
        #master.title("Encrypt Message")
        self.Init_Val  = StringVar()
        self.Init_Val.set('0')
        

        self.grid()
        
        self.createWidgets()
         

    def create_menu(self):
        menu = Menu(self.master)
        self.master.config(menu=menu)
        filemenu = Menu(menu)
        menu.add_cascade(label="Menu", menu=filemenu,font=('helevitca','14','bold'),background='aqua')
     
        filemenu.add_command(label="Decrypt Windo", command=lambda:dcrkey('d'))
        filemenu.add_command(label="Make Keys Windo", command=lambda:dcrkey('k'))
        filemenu.add_separator()
        filemenu.add_command(label="Quit", command=lambda:exit())
        

    def createWidgets(self):
        
#-----------------------------------------Encrypt Win Name ---------------------------------
        self.btn01 = Button(self,text='Encrypt Msg',font=('helevitca','12'),fg='black',bg='lime',relief='raised',bd=3,command=lambda:rsa_encryptPW())
        self.btn01.grid(row=0,column=0)


#----------------------------------Enter Msg Label-----------------------------------------
        self.label1 = Label(self,text='VV Enter Your Msg Below VV',font=('helevitca','14'),bg="#fff")
        self.label1.grid(row=4,column=1)

#----------------------------------Exit Button-----------------------------------------
        self.btn04 = Button(self,text='Exit',font=('helevitca','12'),bg="pink",fg='black',relief='raised',bd=3,command=lambda:exit())
        self.btn04.grid(row=0,column=4)
#----------------------------------Entry Filename-----------------------------------------
        self.label2 = Label(self,text="Rx's PublicKey Filename(inc ext)",font=('helevitca','12'),bg="#fff",justify='left')
        self.label2.grid(row=1,column=0)
#----------------------------------Password label-----------------------------------------
        self.label4 = Label(self,text='Message Filename(inc ext)',font=('helevitca','12'),bg="#fff",justify='left')
        self.label4.grid(row=4,column=0)
#----------------------------------Password label-----------------------------------------
        self.label4 = Label(self,text='Password Filename(inc ext)',font=('helevitca','12'),bg="#fff",justify='left')
        self.label4.grid(row=3,column=0)
#----------------------------------Password name-----------------------------------------
        self.label5 = Label(self,text="Enter an ASCII Password",font=('helevitca','12'),bg="#fff",justify='left')
        self.label5.grid(row=2,column=0)
#--------------------------Rxr Public key Entry -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry1=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry1.grid(row=1,column=1)
#--------------------------Message File Name Entry -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry2=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry2.grid(row=4,column=1)
#--------------------------Password File Name Entry -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry3=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry3.grid(row=3,column=1)
#------------------------------------------password entry------------------------------------------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry4=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry4.grid(row=2,column=1)
#------------------------------------------Text win------------------------------------------------
        self.ftext = ScrolledText(font=("Helvetica",14,'bold'),width=65,height=30)
        self.ftext.grid(row=3,column=0)
        self.ftext.focus_set()        
#-----------------------------------------------------------------------------------------

        self.create_menu()
#---------------------------------------





class DecryptGen(Frame): #Encrypt window
    
    
    def __init__(self,master):
        Frame.__init__(self,master,bg="white")
        self.master = master
        #master.title("Decrypt Message")
        self.Init_Val  = StringVar()
        self.Init_Val.set('0')
        

        self.grid()
        
        self.createWidgets()
         

    def create_menu(self):
        menu = Menu(self.master)
        self.master.config(menu=menu)
        filemenu = Menu(menu)
        menu.add_cascade(label="Menu", menu=filemenu,font=('helevitca','14','bold'),background='aqua')
        
        filemenu.add_command(label="Encrypt Windo", command=lambda:enckey('e'))
        #filemenu.add_command(label="Make Keys Windo", command=lambda:enckey('k'))
        #filemenu.add_command(label="Decrypt Windo", command=lambda:dcrkey('d'))
        filemenu.add_separator()
        filemenu.add_command(label="Quit", command=lambda:exit())
        

    def createWidgets(self):
        
#-----------------------------------------Encrypt Win Name ---------------------------------
        self.btn01 = Button(self,text='Decrypt Msg',font=('helevitca','12'),fg='black',bg='lime',relief='raised',bd=3,command=lambda:rsa_decrypt())
        self.btn01.grid(row=0,column=0)


#----------------------------------Enter Msg Label-----------------------------------------
        self.label1 = Label(self,text='VV Enter Your Msg Below VV',font=('helevitca','14'),bg="#fff")
        self.label1.grid(row=4,column=1)

#----------------------------------Exit Button-----------------------------------------
        self.btn04 = Button(self,text='Exit',font=('helevitca','12'),bg="pink",fg='black',relief='raised',bd=3,command=lambda:exit())
        self.btn04.grid(row=0,column=4)
#----------------------------------Entry Filename-----------------------------------------
        self.label2 = Label(self,text="Your PrivateKey Filename(inc ext)",font=('helevitca','12'),bg="#fff",justify='left')
        self.label2.grid(row=1,column=0)
#----------------------------------Password label-----------------------------------------
        self.label4 = Label(self,text='Message Filename(inc ext)',font=('helevitca','12'),bg="#fff",justify='left')
        self.label4.grid(row=4,column=0)
#----------------------------------Password label-----------------------------------------
        self.label4 = Label(self,text='Password Filename(inc ext)',font=('helevitca','12'),bg="#fff",justify='left')
        self.label4.grid(row=3,column=0)
#----------------------------------Password name-----------------------------------------
        #self.label5 = Label(self,text="Enter a Password",font=('helevitca','12'),bg="#fff",justify='left')
        #self.label5.grid(row=2,column=0)

#--------------------------Private key Entry -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry1=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry1.grid(row=1,column=1)

#--------------------------Message File Name Entry -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry3=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry3.grid(row=4,column=1)
#--------------------------Password File Name Entry -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry4=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry4.grid(row=3,column=1)
#------------------------------------------password entry------------------------------------------------
        #patText = StringVar()  #Type it
        #patText.set('')
        #self.entry4=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        #self.entry4.grid(row=2,column=1)
#------------------------------------------Text win------------------------------------------------
        self.ftext = ScrolledText(font=("Helvetica",14,'bold'),width=65,height=30,wrap=WORD)
        self.ftext.grid(row=3,column=0)
        self.ftext.focus_set()        

#-----------------------------------------
        self.create_menu()
#---------------------------------------

def wait():
    time.sleep(1)
    return    

root=Tk()
root.title("AEC Coder(RSApw) vers 1.1")

#encptgenwin=EncryptGen(root)
#decrpgenwin=DecryptGen(root)
global keygenwin,encptgenwin,decrpgenwin
encptgenwin=EncryptGen(root)
#keygenwin=KeyGen(root)

root.mainloop()




