Wolf from Zero Programming - Create Simple Encryption Programs with Python (8)

This is the last one. The encryption applet has been finished, or you can pack it and take it away.

This article lists several improvements for the purpose of:
- Try to improve the user experience
- DEBUG

I. Fix the Bugs

BUG due to different order of function parameters

Previously, I was too excited to finish writing. Yesterday I took the patience to walk through all the functions (forgive me, I won't write the test yet). The result was:

  • Generation key is OK
  • DES Encryption and Decryption Normal
  • RSA encryption and decryption is normal
  • The key cannot be read in mixed mode. The error message is as follows:
  File "E:\crypto\crypto\base.py", line 44, in getPubKey
    pub_key = rsa.PublicKey.load_pkcs1(keydata)
  File "C:\Python34\lib\site-packages\rsa\key.py", line 75, in load_pkcs1
    return method(keyfile)
  File "C:\Python34\lib\site-packages\rsa\key.py", line 243, in _load_pkcs1_pem
    der = rsa.pem.load_pem(keyfile, 'RSA PUBLIC KEY')
  File "C:\Python34\lib\site-packages\rsa\pem.py", line 91, in load_pem
    raise ValueError('No PEM start marker "%s" found' % pem_start)
ValueError: No PEM start marker "b'-----BEGIN RSA PUBLIC KEY-----'" found
  • Digital signature, positive and negative verification are normal

For this reason, I turned on mixed mode, RSA, and the called base at the same time, comparing rows by rows, and concluded that the mixed mode and the corresponding call portion of RSA are identical and cannot be mistaken.I thought the specific method call happened in crypto.py, and I opened it to look at the code again and found the following differences:

# crypto.py
mymix.encMix(rawfilename,key_filename,mode,operation)

# mymix.py
def encMix(key_filename,rawfilename,mode,operation):

# myrsa.py
def encFile(rawfilename,key_filename,mode,operation):

The only difference is that encMix() has a different parameter name location than the other two, and when called in crypto, the path to the source file is passed to the key file, making it unreadable.When I wrote it myself, each function was tested separately, the file path was input, and the order of parameters used within a single module was the same, so I found no problems.

Sure enough, after modifying the parameter order, it works fine.Here the whole program will run completely.

Focus stopped at DES initial value after successful operation

DES encryption is commonly used in testing. It is found that although the input boxes are empty after successful operation (an improvement later in this article), the mouse focus is at the initial DES value, and there will be a pop-up window unless the user enters 8 bytes.

Find found that in DES mode, the DES initial value is the last content entered using focus, and the source file at the end of the step is usually selected by browsing the file.

Previously, it was thought that each input box would default to'disabled'and that activation would be determined after the mode was selected, which would also look good and happen to solve this BUG.

# ginterface.py

# Component default disabled state
des_key_entry = Entry(key_frame,**state='disabled'**,textvariable=des_key)

#Execute Button Call Method
def cryption():
    ...
    #Empty Input Box
    if textVar == 'Operation Completed':
        mode_choice.set('')
        operation_choice.set('')
        des_key_entry.delete(0,END)
        des_key_entry['state'] = 'disabled'  #Restore disabled state after emptying

2. Improvement

DES Key Validation

The DES key and initial value must be 8 bytes, and the validation of the entry component is complete without the need for event binding.

For content validation of entry components, you can see Explanation of Fish C , very detailed

I want to trigger validation when the user leaves the input box, empty the input box if it is less than 8 bytes, and pop up a prompt box; to empty the input box, the delete() method must be called, so there is no way to have the DES key and initial value validation use the same method; the popup prompt box can use mess, a standard tkinter dialog boxAgebox

# ginterface.py

# Verify the validity of DES keys and initializers
def valiDeskey():
    if len(des_key.get()) == 8:
        return True
    else:
        des_key_entry.delete(0,END)  # Empty directly instead of 8 bytes
        messagebox.showerror('Input error','Please enter 8 bytes DES secret key',default='ok',icon='warning')
        return False   # The return of a validation function must be True or False

# DES Key
...
des_key_entry = Entry(key_frame,textvariable=des_key,validate='focusout',validatecommand=valiDeskey,width=10,show='*')
...

The validation of the DES initializer is exactly the same, except that the corresponding function and variable names are changed.

The current way of writing requires that once the user chooses to enter the DES key, he or she must ensure that he or she enters 8 bytes. Doing anything else in the middle of the way will cause the input box to lose focus, or pop up a prompt.

Improve Mode Selection

The current logic is that when the focus is off, the user will decide which input box in the key area is available based on the selected mode and operation, but I set the default values to DES and encryption. The user may not focus on the mode selection box at all, so the input box state will not be changed.I don't allow this!

Delete code that sets default values for modes and operations to appropriately match user selection.

Clear input after successful operation

Users are likely to start an RSA operation immediately after a DES operation, which should restore the software interface to its newly opened state, i.e. empty all input boxes.I added the empty action to the Execute Action method and it will not be emptied until the user has succeeded.

# ginterface.py

def cryption():
    ...
    #Empty Input Box
    if textVar == 'Operation Completed':
        mode_choice.set('')
        operation_choice.set('')
        des_key_entry.delete(0,END)  # Entry component has no set method
        des_IV_entry.delete(0,END)
        key_filename_entry.delete(0,END)
        sig_filename_entry.delete(0,END)
        rawfilename_entry.delete(0,END)

Add dialog emptying

When the user feels that the dialog box has too much content, they can empty it with one click.At the same time, to avoid the user entering anything at will in the dialog box, I set the default state of the dialog box to disabled and restore normal briefly only when the printing operation is progressing or empty

# ginterface.py

text = Text(height=10,width=60,bd=3,relief=SUNKEN,wrap=WORD,state='disabled') 
#Height, Width, Border Width and Style, Wrap by Word
text.pack(padx=1,pady=5)
def empty():
    text['state'] = 'normal'
    text.delete(1.0,END)  #1.0 is the starting position
    text['state'] = 'disabled'
empty_button = Button(text='Empty Dialog',command=empty)
empty_button.pack(padx=20,pady=5,side=RIGHT)

Capture error information

In order for the user to click the "Execute Action" button whenever he wants to enter it, he or she needs to capture the error information in the code and give a hint about the error mode selected by the user.

The original

# ginterface.py

def cryption():
    ...
    textVar = crypto.doCrypto(mode,operation,des_key,des_IV,key_filename,sig_filename,rawfilename)
    text['state'] = 'normal'
    text.insert(END,textVar)
    text.insert(END,'\n')
    text['state'] = 'disabled'

Change to

def cryption():
    ...
    try:
        textVar = crypto.doCrypto(mode,operation,des_key,des_IV,key_filename,sig_filename,rawfilename)
    except:
        textVar = 'Please enter the parameters correctly'
    text['state'] = 'normal'
    text.insert(END,textVar)
    text.insert(END,'\n')
    text['state'] = 'disabled'

Then in'crypto.py', assign a value to the return value according to the user's choice, for example, if the user chooses DES-signature, it returns'Please select the correct operation', the test result is as follows:

Install a vertical scrollbar to the progress dialog

The Scrollbar component of tkinter can install vertical and horizontal scrollbars for the Text component. What I need to do is:
-Create a new Frame component as the parent of the dialog box and scrollbar
- Set the yscrollcommand option of the Text component to set() of the Scrollbar component
- Set the command option of the Scrollbar component to yview() of the Text component

#ginterface.py

#Dialog Frame, which facilitates typesetting
text_frame = Frame(root)
text_frame.pack()

#Scrollbars and dialogs
textbar = Scrollbar(text_frame,takefocus=False)  #Scrollbars do not require focus
textbar.pack(side=RIGHT,fill=Y)
text = Text(text_frame,height=10,width=60,bd=3,yscrollcommand=textbar.set,relief=SUNKEN,wrap=WORD,state='disabled')
#Height, Width, Border Width and Style, Wrap by Word
text.pack(side=RIGHT,fill=BOTH)
textbar['command'] = text.yview  #yview is a Text component built-in method

Empty Invalid Input Box

Users may choose DES mode first, after entering the key, they find that they have chosen the wrong one. It should be RSA mode, which must be changed directly. The DES key that has been entered needs to be cleared automatically before it is disabled.

You just need to add a line to the pattern judgment to empty it, but only add that line to the input box that needs to be disabled.

# ginterface.py

def judgMode(event):
    if mode.get() == 'DES':
        des_key_entry['state'] = 'normal'
        des_IV_entry['state'] = 'normal'
        **key_filename_entry.delete(0,END)**
        **sig_filename_entry.delete(0,END)**
        key_filename_entry['state'] = 'disabled'
        sig_filename_entry['state'] = 'disabled'

Even though this little software has been completed so far, there are still some features that you can't think of for a while, such as:

  • Allow file selection only by browsing files to avoid user input errors
  • Progress Dialog Real-time Print Code Execution Progress and Operation Time-consuming

Ugly code also needs to be optimized constantly. In short, I'll do it while I'm learning. github repository It will be updated immediately.

Keywords: less github

Added by latino.ad7 on Fri, 12 Jul 2019 19:50:41 +0300