#Added ability to encrypt from a file 3.0

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
from PIL import Image, ImageFilter
from io import BytesIO

chunksize = 64*126000  # determines size of image allowed
key_size = 1024
size = 16

def genKeys():
    global key_size
    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
    if emsg == "PICtuRE":
        myimage=encptgenwin.entry5.get()#get image filename
        emsg = emsg + myimage #add file name to PW
    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():
    global size,chunksize
    password =  encptgenwin.entry4.get() # get password
    if password == "PICtuRE": 
        myimage=encptgenwin.entry5.get()#get image filename
        #print(myimage)
        try:
            with open(myimage, 'rb') as f:
                picimage=f.read() #READ data
        except:
            encptgenwin.ftext.insert(END,'Bad Image filename, Check Ext!\n')
            return
        emsg = bytearray(picimage)
        password = password + myimage
        #print("password",password)
    elif encptgenwin.checkVar.get() == True:
        mymsg = encptgenwin.entry6.get() # get message file
        try:
            with open(mymsg,'r') as f:
                emsg=f.read()
        except:
            encptgenwin.ftext.insert(END,'Bad Message filename, Check it!\n')
            return
    else:
        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*2048
    #outputfile =   encptgenwin.entry2.get() #get file name to save encryption to.
    #password =  encptgenwin.entry4.get() # get password
    key = getKey(password)
    if password[:7] == "PICtuRE":
        chunk = emsg #bytes(emsg)
    else:
        chunk = bytes(emsg,'utf-8')
    chunk += b' ' * (size - (len(chunk) % size))
    filesize = str(len(emsg)).zfill(size)
    IV = Random.new().read(size)

    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()
#--------------------------process Image-------------------------
def process_image(decoded,imageFile):
    #print(imageFile)
    #im = decoded 
    #Display image
    #decoded.show()
    #print(decoded)
    #image = Image.open(BytesIO(decoded))  #<---- this works without saving file too
    #print('The format of img is: ', image.format)
    #print('The mode of img is: ', image.mode)
    #print('The size of img is: ', image.size)
    #print('The palette of img is: ', image.palette)
    #size = image.size
    #newsizeimage = image.resize((int(size[0]*.5), int(size[1]*.5)))
    #print("newsize:" ,newsizeimage.size)

    #image = im.save('test.jpg')
    with open(imageFile, 'wb+') as outfile:
        outfile.write(decoded)
    #with open('test2.jpg', 'rb') as image:
        #image.read()
    image=Image.open(imageFile)
    #image = BytesIO(image)
    #image = Image.open(BytesIO(decoded))
    image.show()
    decptgenwin.ftext.insert('1.0',"Image Saved in File: "+imageFile+"\n")
    return
def save_pic(decoded):
    file_obj = open("test3.jpg", "wb+") #save decoded image
    file_obj.write(decoded)
    file_obj.close()
    return
#------------------------decrypt MSG--------------------------------
def aec_decrypt():
    global PassWord,size,chunksize
    #chunksize = 64*2048
    filename = decptgenwin.entry3.get() # get filname to decrypt
    #password =   decryptwin.entry3.get() # get password
    key = getKey(PassWord)
    #print("key",key)
    #print("PassWord",PassWord)
    try:
        with open(filename, 'rb') as infile:
            filesize = int(infile.read(size))
            IV = infile.read(size)
            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)
    #print("here1")
    if PassWord[:7] == "PICtuRE":
        #save_pic(decoded)
        #print("here2")
        #print(PassWord[7:])
        process_image(decoded,PassWord[7:])
        
        return
    else:
        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(no ext)',font=('helevitca','12'),bg="#fff",justify='left')
        self.label2.grid(row=1,column=0)
#----------------------------------Password label-----------------------------------------
        self.label4 = Label(self,text='Private Filename(no 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)
#---------------------------------Use File Message Checkbutton ---------------------------------------------
        self.checkVar = IntVar()
        self.check = Checkbutton(self,text='Use Message File to Encrypt', variable=self.checkVar, onvalue=True, offvalue=False)
        self.check.grid(row=0,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(+ext)",font=('helevitca','12'),bg="#fff",justify='left')
        self.label2.grid(row=1,column=0)
#----------------------------------Password label-----------------------------------------
        self.label4 = Label(self,text='Encrypted Message Filename(+ext)',font=('helevitca','12'),bg="#fff",justify='left')
        self.label4.grid(row=4,column=0)
#----------------------------------Password label-----------------------------------------
        self.label4 = Label(self,text='Encrypted Password Filename(+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)
#----------------------------------Image filename-----------------------------------------
        self.label5 = Label(self,text="Enter Image Filename(inc ext)",font=('helevitca','12'),bg="#fff",justify='left')
        self.label5.grid(row=5,column=0)
#----------------------------------Message to encrypt filename-----------------------------------------
        self.label5 = Label(self,text="Message to Encrypt Filename(+ext)",font=('helevitca','12'),bg="#fff",justify='left')
        self.label5.grid(row=6,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)
#--------------------------Image File Name Entry -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry5=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry5.grid(row=5,column=1)
#--------------------------Message to encrypt filename -----------------
        patText = StringVar()  #Type it
        patText.set('')
        self.entry6=Entry(self,textvariable=patText,fg="black",bg='#ddd',font=("Helvetica",12,'bold'),justify='center',width=30)
        self.entry6.grid(row=6,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/AECmsg) vers 3.0")

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

root.mainloop()




