python3 + wxpython 实现 AES 加密工具


2018年8月2日17:02:00 【原创】
目录:python 编程博客 索引

1. 运行环境

最近打算使用 python3 写一个图形化的加密工具,使用 AES 加密

另外我的环境使用了 wxpython 图形化模块,安装方法也很简单

pip install wxpython
pip install pyinstaller
pip install pycryptodome

wxpython 已经更新到版本 4.0 了,在这里的小软件中的环境是可以兼容使用的

打包成文件

pyinstaller -F -w -i C:\Users\John\Desktop\pythonworkV4.0\icon.ico C:\Users\John\Desktop\pythonworkV4.0\setup.py

2. 功能简介

1. 选择自定义的密钥文件
2. 选择自定义的明文文件
3. 加密成密文并显示
4. 选择密文文件
5. 选择呢密钥文件
6. 进行解密并显示出明文
  1. 主界面
  2. 代码下载
    python3 + wxpython 实现 AES 加密工具

3. 程序代码

# coding:UTF-8
#pip3 install pycryptodome
		
import wx
import os
import random, sys
from Crypto.Cipher import AES
wildcard1 = u"文本文件 (*.txt)|*.txt|"    \
           "All files (*.*)|*.*"
wildcard2 = u"文本文件 (*.txt)|*.txt|"    \
           "All files (*.*)|*.*"
fileDir = os.getcwd()

class MultiTextFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, u"AES 加密工具",
                          size=(600, 400))

        global filepath1, filepath2, filepath3, Key, Text
        keysize = 0
        fileDir = os.getcwd()

        panel = wx.Panel(self, -1)
        #panel.SetBackgroundColour('#c0c3c8')
        #font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
        font = wx.Font(9, wx.ROMAN, wx.NORMAL, wx.BOLD, False)
        fontbt = wx.Font(9, wx.ROMAN, wx.NORMAL, wx.BOLD, False)
        fontms = wx.Font(15, wx.ROMAN, wx.NORMAL, wx.NORMAL, False)
        font.SetPointSize(9)

        #vbox:纵向排列的容器
        vbox = wx.BoxSizer(wx.VERTICAL)

        vbox.Add((-1, 5))  #预留15像素空白,vbox6此行开始

        #st7:“密钥文件”
        hbox8 = wx.BoxSizer(wx.HORIZONTAL)
        
        st5 = wx.StaticText(panel, 0, label=u'密钥文件:', style=wx.TE_LEFT) #静态文本
        st5.SetFont(font)
        hbox8.Add(st5,proportion=0,flag=wx.LEFT|wx.RIGHT,border = 15)    #静态文本的左右空间15
        #filepath1: 密钥路径
        filepath3 = wx.TextCtrl(panel, size=(1024,30))
        hbox8.Add(filepath3,proportion=1,flag=wx.ALIGN_LEFT)
        #btn3:“浏览一”
        btn4 = wx.Button(panel, label=u'浏览', size=(70, 30))
        btn4.SetFont(fontbt)
        hbox8.Add(btn4,proportion=0,flag=wx.RIGHT|wx.LEFT, border=15)    #按钮3的左右空间15

        vbox.Add(hbox8, proportion=1,flag= wx.BOTTOM | wx.TOP, border=15)    #三部分水平分布

        #st3:明文文件
        hbox6 = wx.BoxSizer(wx.HORIZONTAL)
        st3 = wx.StaticText(panel, 0, label=u'明文文件:', style=wx.TE_LEFT) #静态文本
        st3.SetFont(font)
        hbox6.Add(st3,proportion=0,flag=wx.LEFT|wx.RIGHT,border = 15)    #静态文本的左右空间15
        #filepath1: 明文路径
        filepath1 = wx.TextCtrl(panel, size=(1024,30))
        hbox6.Add(filepath1,proportion=1,flag=wx.ALIGN_LEFT)
        #btn3:“浏览上”
        btn3 = wx.Button(panel, label=u'浏览', size=(70, 30))
        btn3.SetFont(fontbt)
        hbox6.Add(btn3,proportion=0,flag=wx.RIGHT|wx.LEFT, border=15)    #按钮3的左右空间15

        vbox.Add(hbox6, proportion=1,flag= wx.BOTTOM, border=10)    #三部分水平分布
        
        #vbox.Add((-1, 5))  #预留15像素空白
        
        #st1:“明文”
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)

        #tc1: 明文文本框内容
        #hbox1.Add(st1, flag=wx.RIGHT, border=10)    #明文区域左空间
        self.tc1 = wx.TextCtrl(panel,size=(400,70),style=wx.TE_MULTILINE | wx.TE_RICH2 )
        self.tc1.SetFont(fontms)
        hbox1.Add(self.tc1, proportion=1, flag=wx.EXPAND | wx.LEFT ,border=30)
        vbox.Add(hbox1, proportion=1, flag= wx.RIGHT | wx.EXPAND, border=10)   #明文区域右空间

        #vbox.Add((-1, 5))  #预留15像素空白

        #st4:“密文文件:”
        hbox6 = wx.BoxSizer(wx.HORIZONTAL)
        st4 = wx.StaticText(panel, 0, label=u'密文文件:', style=wx.TE_LEFT) #静态文本
        st4.SetFont(font)
        hbox6.Add(st4,proportion=0,flag=wx.LEFT|wx.RIGHT,border = 15)    #静态文本的左右空间15
        #filepath2: 密文路径
        filepath2 = wx.TextCtrl(panel, size=(1024,30))
        hbox6.Add(filepath2,proportion=1,flag=wx.ALIGN_LEFT)
        #btn5:“浏览下””
        btn5 = wx.Button(panel, label=u'浏览', size=(70, 30))
        btn5.SetFont(fontbt)
        hbox6.Add(btn5,proportion=0,flag=wx.RIGHT|wx.LEFT, border=15)    #按钮3的左右空间15

        vbox.Add(hbox6, proportion=1, flag= wx.BOTTOM | wx.TOP, border=15)    #三部分水平分布
 

        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        #tc2: 密文文本框内容
        self.tc2 = wx.TextCtrl(panel, size=(400,800),style=wx.TE_MULTILINE | wx.TE_RICH2 | wx.TE_READONLY) # wx.HSCROLL 不自动换行
        self.tc2.SetFont(fontms)
        hbox3.Add(self.tc2, proportion=1, flag=wx.EXPAND | wx.LEFT ,border=30)
        vbox.Add(hbox3, proportion=1, flag= wx.RIGHT |wx.BOTTOM| wx.EXPAND,border=10)    #密文区域右空间




        hbox5 = wx.BoxSizer(wx.HORIZONTAL)
        #btn1:"RSA加密"
        btn1 = wx.Button(panel, label=u'加密', size=(110, 30))
        btn1.SetFont(font)
        hbox5.Add(btn1, flag=wx.LEFT , border=50)
        #btn2:“RSA解密”
        btn2 = wx.Button(panel, label=u'解密', size=(110, 30))
        btn2.SetFont(font)
        hbox5.Add(btn2, flag=wx.LEFT , border=50)    #两个按钮中间空间

        vbox.Add(hbox5, flag=wx.ALIGN_CENTER_HORIZONTAL, border=30) #三个按钮右空间
        vbox.Add((-1, 15))  #预留15像素空白

      

        panel.SetSizer(vbox)

        '''绑定事件'''
        
        #ipaddr: IP地址栏
        #filepath1: 明文路径
        #filepath2: 密文路径
        #filepath3: 密钥路径
      
        #tc1: 明文文本框内容
        #tc2:密文文本框内容

        self.Bind(wx.EVT_BUTTON, self.encryptMessage, btn1)     #加密
        self.Bind(wx.EVT_BUTTON, self.decryptMessage, btn2)     #解密
        self.Bind(wx.EVT_BUTTON, self.openplaintextfile, btn3)  #浏览2
        self.Bind(wx.EVT_BUTTON, self.openkeyfile, btn4)  #浏览1
        self.Bind(wx.EVT_BUTTON, self.openciphertextfile, btn5) #浏览3



    #加密内容需要长达16位字符,所以进行空格拼接
    def pad(self,Text):
        #global Text
        while len(Text) % 16 != 0:
            Text += b' '
        return Text

    
    #加密秘钥需要长达16位字符,所以进行空格拼接
    def pad_key(self,Key):
        # global Key
        while len(Key) % 16 != 0:
            Key += b' '
        return Key


    def encryptMessage(self, event):
        try:
            #self.tc1.Clear()
            self.tc2.Clear()  
           
            tc1data = self.tc1.GetValue()
            #global Key
            keyfile = filepath3.GetValue()
            fo = open(keyfile)
            Key = fo.read().encode('utf-8')
            fo.close()
            #print(Key)
        
            
            #进行加密算法,模式ECB模式,把叠加完16位的秘钥传进来
            aes = AES.new(self.pad_key(Key), AES.MODE_ECB)
            #加密内容,此处需要将字符串转为字节


            #Text = b'woshijiamineirong'
            #global Text
            msgfile = filepath1.GetValue()
            fo = open(msgfile)
            Text = fo.read().encode('utf-8')
            fo.close()
            #print(Text)

            #进行内容拼接16位字符后传入加密类中,结果为字节类型

            encrypted_text = aes.encrypt(self.pad(Text))
            #print('密文:')
            #print(encrypted_text)

            cryptedfile = filepath2.GetValue()
            fo = open(cryptedfile,'wb')
            
            fo.write(encrypted_text)
            fo.close()
            crymsg = str(encrypted_text, encoding='utf8',errors="ignore")
            self.tc2.SetValue(crymsg)

        except FileNotFoundError:
            messagedata = u'参数输入不正确'
            dlg = wx.MessageDialog(self, messagedata, caption='提示', style = wx.OK|wx.ICON_ERROR)
            dlg.ShowModal()
       
    def decryptMessage(self, event):

            self.tc1.Clear()
            self.tc2.Clear()
            tc2data = self.tc2.GetValue()
        
            dlg6 = wx.FileDialog(
                    self,defaultFile="key.txt",
                    message=u"请选择密钥文件",
                    defaultDir=fileDir,
                    wildcard=wildcard1,
                    style=wx.FD_OPEN | wx.FD_MULTIPLE)
            if dlg6.ShowModal() == wx.ID_OK:
                dlg1 = wx.FileDialog(
                    self,defaultFile="encryted.txt",
                    message=u"请选择密文文件",
                    defaultDir=fileDir,
                    wildcard=wildcard1,
                    style=wx.FD_OPEN | wx.FD_MULTIPLE)
                if dlg1.ShowModal() == wx.ID_OK:
                    if os.path.exists(dlg1.GetPath()) == True:
                        keyfile2 = dlg6.GetPath()
                        filepath3.SetValue(keyfile2)

                        msgfile2 = dlg1.GetPath()
                        filepath2.SetValue(msgfile2)
                

                        #此处是为了验证是否能将字节转为字符串后,进行解密成功
                        #实际上a 就是 encrypted_text ,也就是加密后的内容
                        #用aes对象进行解密,将字节类型转为str类型,错误编码忽略不计
                        #获取str从0开始到文本内容的字符串长度。

                        fo = open(msgfile2,'rb')
                        msg2 = fo.read()
                        fo.close()
                        msg22 =  str(msg2, encoding='utf8',errors="ignore")
                        self.tc2.AppendText(msg22)
                        #print(msg2)

                        fo = open(keyfile2,'rb')
                        key2 = fo.read()
                        fo.close()
                        #print(key2)

                        aes = AES.new(self.pad_key(key2), AES.MODE_ECB)
                        de = str(aes.decrypt(msg2),encoding='utf-8',errors="ignore")
                        #print('明文:')
                        #print(de[:len(msg2)])

                        self.tc1.AppendText(de)
                    

    def openplaintextfile(self, event):
        dlg = wx.FileDialog(
            self,defaultFile="message.txt",
            message=u"选择明文文件",
            defaultDir=fileDir,
            wildcard=wildcard1,
            style=wx.FD_OPEN | wx.FD_MULTIPLE)
        dlg.SetDirectory(fileDir)
        if dlg.ShowModal() == wx.ID_OK:
            tmp=""
            paths = dlg.GetPaths()
            for path in paths:
                tmp=tmp+path
            filepath1.SetValue(tmp)
            file=open(filepath1.GetValue())
            self.tc1.SetValue(file.read())
            file.close()
            #print('明文文件打开成功!')
            #self.tc3.AppendText('\n明文文件打开成功!')
        
        dlg.Destroy()
    

    def openciphertextfile(self,event):
        dlg = wx.FileDialog(
            self,defaultFile="encryted.txt",
            message=u"选择密文保存位置",
            defaultDir=fileDir,
            wildcard=wildcard1,
            style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
        if dlg.ShowModal() == wx.ID_OK:
            tmp=""
            paths = dlg.GetPaths()
            for path in paths:
                tmp=tmp+path
            filepath2.SetValue(tmp)

        dlg.Destroy()


    def openkeyfile(self,event):

        dlg = wx.FileDialog(
            self,defaultFile="key.txt",
            message=u"选择密钥文件",
            defaultDir=fileDir,
            wildcard=wildcard1,
            style=wx.FD_OPEN | wx.FD_MULTIPLE)
        dlg.SetDirectory(fileDir)
        if dlg.ShowModal() == wx.ID_OK:
            tmp=""
            paths = dlg.GetPaths()
            for path in paths:
                tmp=tmp+path
            filepath3.SetValue(tmp)
            file=open(filepath3.GetValue())
            global Key
            Key = file.read().encode('utf-8')
            file.close()
        dlg.Destroy()


class MyApp(wx.App):
    def __init__(self):
        # 重构__init__方法,将错误信息重定位到文件中;
        # 默认redirect=True,输出到StdOut或StdError;
        # 为防止程序因错误一闪而过无法捕捉信息,可在
        # 控制台中使用python -i example.py来运行程序。
        wx.App.__init__(self, redirect=True)

    def OnInit(self):
        frame = MultiTextFrame()
        frame.Show(True)
        return True

def main():
    app = MyApp()
    app.MainLoop()

if __name__ == "__main__":
    main()