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.