python實現一個加密的文字處理器

来源:https://www.cnblogs.com/godforever/archive/2022/06/03/16340248.html
-Advertisement-
Play Games

這是一個類似於記事本的文字處理器。與正常的記事本不同的是,它會將文本文檔進行加密,確保無法被常規的程式打開。 由於本人是一位業餘編程愛好者,對於“python之禪”之類的規則比較不以為然,因此本程式代碼也許有些許凌亂(當然不利於後期修改)。 這篇文章我早已發佈過,但當時只給出了代碼,並加了一些註釋。 ...


這是一個類似於記事本的文字處理器。與正常的記事本不同的是,它會將文本文檔進行加密,確保無法被常規的程式打開。

由於本人是一位業餘編程愛好者,對於“python之禪”之類的規則比較不以為然,因此本程式代碼也許有些許凌亂(當然不利於後期修改)。

這篇文章我早已發佈過,但當時只給出了代碼,並加了一些註釋。現在,我希望在這裡詳細解釋這個程式。

首先,對於一個適合我們廣大中華兒女使用的程式,我們不可避免地要使用中文。這就需要對編碼進行聲明:

# coding:utf-8

然後,就到了模塊導入的環節了。我們這裡需要tkinter,windnd,os和sys。windnd可以用pip安裝,tkinter則需要在安裝python時勾選:

from tkinter import *
from tkinter.filedialog import *
from tkinter.messagebox import *
import windnd
import os
import sys

接下來,我們會看到這樣一段代碼:

try:
    filename = sys.argv[1]
except:
    filename = ""

這是乾什麼的呢?我們知道,對於exe程式,有一個“Open with”功能,也就是可以將拖動到exe文件或其快捷方式的文件打開。事實上,py文件也有這個功能,但是多數情況下這樣操作後只能使程式正常運行,而不能對文件進行任何操作。而“sys.argv[1]”的作用就是,讀取這個文件的路徑信息。這樣,我們就可以用open或sys庫里的一些指令進行對文件的操作了。

def encryption(c, d):
    c = list(c + d)
    g=list(d)
    d=0
    for i in g:
        d*=ord(i)
        d=round(abs(d)**0.5)
    f="0x"
    for i in c:
        e=str(ord(i)+d)
        d=round(300*(d**0.5))
        f=f+e+"a"
    f=eval(f[:-1])
    return (f)
def decrypt(c,d): c=hex(int(c)) print(c) c=c[2:].split("a") z=d g = list(d) d = 0 for i in g: d *= ord(i) d = round(abs(d) ** 0.5) f="" for i in c: e = chr(int(i)-d) d = round(300 * (d ** 0.5)) f = f + e if f[-len(z):]==z: f=f[:-len(z)] return (f) else: c="bbc"+12

這一段就比較勁爆了。它定義了兩個函數,一個用於加密,另外一個用於解密(順便說一句,我英語不太好,有的函數或變數的名字可能比較古怪,請見諒)。

encryption是加密的函數(呃,這個應該叫做encrypt,我編這個程式時大腦有些短路,但既然已經這樣了,也就不改了),它會將明文(輸入的c)通過與密鑰d有關的某些運算,得出一個十六進位數,然後將其轉化為十進位。同時,為了確保解密結果唯一,將密鑰一起連接在明文上,起校驗作用。在這裡,對於明文的每一個字元都會將加密過程中實際使用的密鑰進行變動,因此基本是不可能通過字元出現頻率的規律來破解的。由於密鑰是字元,暴力拆解也基本不可能。

decrypt是解密,它大致就是encryption的逆操作,同時如果校驗的結果有誤,或是遇到其他解密失敗的情況它會產生錯誤(因此使用時需要try-except,來確保程式不會退出,同時對解密失敗的情況進行處理)。

接下來是基本的文件操作部分:

def mynew(aaa=1):
    global top, filename, textPad
    top.title("無標題 - 加密文本編輯器")
    filename = None
    textPad.delete(1.0, END)
    textPad.insert(1.0, "")
def myopen(aaa=1): global filename,kkk filename = askopenfilename() if filename == "": filename = None else: top.title(os.path.basename(filename)+" - 加密文本編輯器") format=os.path.basename(filename)[os.path.basename(filename).find(".")+1:] textPad.delete(1.0, END) try: f = open(filename, 'rb') c = f.read() ccc = str(c)[2:-1] ccc.replace("\\","") textPad.insert(1.0,decrypt(ccc,format)) kkk=1 except: f.close() try: f = open(filename, 'r', encoding="gbk") try: c = f.read() except: f.close() f = open(filename, 'r', encoding="utf-8") c = f.read() textPad.insert(1.0, c) kkk = 0 except: f.close() f = open(filename, 'rb') c = f.read() textPad.insert(1.0, c) kkk=0 f.close()
def mysave(aaa=1): global filename,kkk try: msg = textPad.get(1.0, 'end')[0:-1] if kkk==0: f = open(filename, 'w', encoding="utf-8") f.write(msg) else: f = open(filename, 'wb') fffff = str(encryption(msg, format)) fffff = eval("b'{}'".format(fffff)) print(fffff) f.write(fffff) f.close() except: mysaveas() def mysaveas(aaa=1): global filename f = asksaveasfilename(initialfile="無標題.txt") filename = f format = os.path.basename(filename)[os.path.basename(filename).find(".") + 1:] msg = textPad.get(1.0, 'end')[0:-1] if not format == "py" and not format=="bat" and not format == "pyw"and not format == "cmd": fh = open(filename, 'wb') fffff = str(encryption(msg, format)) fffff = eval("b'{}'".format(fffff)) print(fffff) fh.write(fffff) else: fh = open(filename, 'w', encoding="utf-8") fh.write(msg) fh.close() top.title(os.path.basename(f)+" - 加密文本編輯器")
def opened(files): global filename,kkk ff = '\n'.join((item.decode('gbk') for item in files)) filename = ff if filename == "": filename = None else: top.title(os.path.basename(filename) + " - 加密文本編輯器") format = os.path.basename(filename)[os.path.basename(filename).find(".") + 1:] textPad.delete(1.0, END) try: f = open(filename, 'rb') c = f.read() ccc = str(c)[2:-1] ccc.replace("\\", "") textPad.insert(1.0, decrypt(ccc, format)) kkk = 1 except: f.close() try: f = open(filename, 'r', encoding="gbk") try: c = f.read() except: f.close() f = open(filename, 'r', encoding="utf-8") c = f.read() textPad.insert(1.0, c) kkk = 0 except: f.close() f = open(filename, 'rb') c = f.read() textPad.insert(1.0, c) kkk = 0 f.close()
def mynew(aaa=1):
    global top, filename, textPad
    top.title("無標題 - 加密文本編輯器")
    filename = None
    textPad.delete(1.0, END)
    textPad.insert(1.0, "")

首先說mynew(新建)。這裡有一個可選參數a,這是因為通過bind激活函數會輸入一個參數(這點我非常反感),為了不讓程式運行出錯,就添加了一個可選參數。這個其實沒啥好說。global後面是所需的全局變數,然後就是設置視窗名稱、文件名稱,並清空輸入框,很簡單,很明瞭。

def myopen(aaa=1):
    global filename,kkk
    filename = askopenfilename()
    if filename == "":
        filename = None
    else:
        top.title(os.path.basename(filename)+" - 加密文本編輯器")
        format=os.path.basename(filename)[os.path.basename(filename).find(".")+1:]
        textPad.delete(1.0, END)
        try:
            f = open(filename, 'rb')
            c = f.read()
            ccc = str(c)[2:-1]
            ccc.replace("\\","")
            textPad.insert(1.0,decrypt(ccc,format))
            kkk=1
        except:
            f.close()
            try:
                f = open(filename, 'r', encoding="gbk")
                try:
                    c = f.read()
                except:
                    f.close()
                    f = open(filename, 'r', encoding="utf-8")
                    c = f.read()
                textPad.insert(1.0, c)
                kkk = 0
            except:
                f.close()
                f = open(filename, 'rb')
                c = f.read()
                textPad.insert(1.0, c)
                kkk=0
        f.close()

然後就是myopen(打開)。“filename=askopenfilename()”就是,彈出一個選擇打開的文件的視窗,並將結果存入filename。然後我們獲取文件的尾碼信息,作為解密所需的密鑰。接下來,我們先嘗試解密文件。如果執行中有錯誤,也就是無法解密,則用gbk編碼正常打開,仍然打開失敗,則使用utf-8。當然,如果都失敗了,就用rb模式,也就是位元組流的形式打開。

def mysave(aaa=1):
    global filename,kkk
    try:
        msg = textPad.get(1.0, 'end')[0:-1]
        if kkk==0:
            f = open(filename, 'w', encoding="utf-8")
            f.write(msg)
        else:
            f = open(filename, 'wb')
            fffff = str(encryption(msg, format))
            fffff = eval("b'{}'".format(fffff))
            print(fffff)
            f.write(fffff)
        f.close()
    except:
        mysaveas()

接下來,我們講mysave(保存)。將輸入框中的內容存入變數msg,然後寫入文件,當然,如果filename是None,會產生錯誤,然後執行mysaveas,也就是另存。這裡有一個判定,判定kkk的值是否是1。kkk的值是1,意味著當前打開的文件是曾被加密的文件,因為打開這樣的文件時會自動將kkk設置為1;反之,則只可能是打開的其他未加密文件,如果是這樣,編輯後依然不加密,以免損壞文件。這裡要註意,噹噹前文件為新建文件時,不會執行保存的寫入程式,而是會在另存里執行,因此對於這一類文件的加密與否,不會與kkk掛鉤。

def mysaveas(aaa=1):
    global filename
    f = asksaveasfilename(initialfile="無標題.txt")
    filename = f
    format = os.path.basename(filename)[os.path.basename(filename).find(".") + 1:]
    msg = textPad.get(1.0, 'end')[0:-1]
    if not format == "py" and not format=="bat" and not format == "pyw"and not format == "cmd":
        fh = open(filename, 'wb')
        fffff = str(encryption(msg, format))
        fffff = eval("b'{}'".format(fffff))
        print(fffff)
        fh.write(fffff)
    else:
        fh = open(filename, 'w', encoding="utf-8")
        fh.write(msg)
    fh.close()
    top.title(os.path.basename(f)+" - 加密文本編輯器")

Next,就是mysaveas(另存)。首先,和打開一樣,它會彈出一個視窗,這次是讓你選擇保存路徑和文件名稱(預設是“無標題.txt”)。然後,將選擇內容存入filename(這裡我不知道怎麼搞了一個存入f的冗餘步驟,不過暫時不管它了)。然後呢,同樣地,獲取文件尾碼、保存輸入框內容,接下來就是寫入環節。這裡,我們判斷如何寫入。如果是py文件、bat文件等程式文件,我們當然不能把它們加密,不然就不能運行了,於是,我們就使用最為通用的utf-8編碼給它寫入。但如果是其他的文件,秉著安全第一的理念,我們就得用加密函數來給內容上一個保險,然後將內容寫入。當然,保存完成後,“無標題”的大字就不能出現在視窗上方了,我們要把它改為另存為的程式的名稱。

def opened(files):
    global filename,kkk
    ff = '\n'.join((item.decode('gbk') for item in files))
    filename = ff
    if filename == "":
        filename = None
    else:
        top.title(os.path.basename(filename) + " - 加密文本編輯器")
        format = os.path.basename(filename)[os.path.basename(filename).find(".") + 1:]
        textPad.delete(1.0, END)
        try:
            f = open(filename, 'rb')
            c = f.read()
            ccc = str(c)[2:-1]
            ccc.replace("\\", "")
            textPad.insert(1.0, decrypt(ccc, format))
            kkk = 1
        except:
            f.close()
            try:
                f = open(filename, 'r', encoding="gbk")
                try:
                    c = f.read()
                except:
                    f.close()
                    f = open(filename, 'r', encoding="utf-8")
                    c = f.read()
                textPad.insert(1.0, c)
                kkk = 0
            except:
                f.close()
                f = open(filename, 'rb')
                c = f.read()
                textPad.insert(1.0, c)
                kkk = 0
        f.close()

最後,是opened。細心的人會發現,這不就是myopen嘛!的確,兩個函數很像,可以說是像極了。區別是,它會獲取拖動到該視窗的文件的路徑信息(這個信息原本在輸入的files中),這個步驟代替了askopenfilename()函數。其他部分,兩者的確一模一樣。

top = Tk()
top.title("無標題 - 加密文本編輯器")
top.geometry("1000x600+100+50")

menubar = Menu(top)
menubar.add_command(label="新建", command=mynew)
menubar.add_command(label="打開", command=myopen)
menubar.add_command(label="保存",  command=mysave)
menubar.add_command(label="另存為", command=mysaveas)

menu = Menu(top, tearoff=False)
menu.add_command(label="新建", accelerator="Ctrl+N", command=mynew)
menu.add_command(label="打開", accelerator="Ctrl+O", command=myopen)
menu.add_command(label="保存", accelerator="Ctrl+S",  command=mysave)
menu.add_command(label="另存為", accelerator="Ctrl+Shift+S", command=mysaveas)

這裡嘛,就是搭建tkinter視窗的主要構建。這裡沒什麼講的,都是一些基本操作。唯一值得一提的是,“accelerator=”是設置快捷鍵。但遺憾的是,它只會顯示快捷鍵名稱,仍然需要手動綁定,不然無法使用。

這個是彈出菜單的彈出代碼:

def command(event):
    menu.post(event.x_root, event.y_root)

另一些視窗設置:

top['menu'] = menubar
all=Frame(top)
all.pack(expand=YES, fill=BOTH)
textPad = Text(all,font=('宋體', 14), undo=True)
if filename == "":
    filename = None
    textPad.insert(1.0, "")
else:
    top.title(os.path.basename(filename) + " - 加密文本編輯器")
    format = os.path.basename(filename)[os.path.basename(filename).find(".") + 1:]
    textPad.delete(1.0, END)
    try:
        f = open(filename, 'rb')
        c = f.read()
        ccc = str(c)[2:-1]
        ccc.replace("\\", "")
        textPad.insert(1.0, decrypt(ccc, format))
        kkk = 1
    except:
        f.close()
        try:
            f = open(filename, 'r', encoding="gbk")
            try:
                c = f.read()
            except:
                f.close()
                f = open(filename, 'r', encoding="utf-8")
                c = f.read()
            textPad.insert(1.0, c)
            kkk = 0
        except:
            f.close()
            f = open(filename, 'rb')
            c = f.read()
            textPad.insert(1.0, c)
            kkk = 0
    f.close()

這個是不是又很熟悉呢?沒錯,又是打開文件。這就和開頭的“sys.argv[1]”相對應,是用於Open with的。網上類似記事本的程式真不少,但有這一功能的,我似乎至今沒有見到過。

scroll = Scrollbar(all)
textPad.config(yscrollcommand=scroll.set)
scroll.config(command=textPad.yview)
scroll.pack(side=RIGHT, fill=Y)
textPad.pack(expand=YES,side=RIGHT,fill=BOTH)

又是視窗組件……(話說我為啥要分這麼多段來設置視窗啊!!!(抓狂!))

top.bind("<Control-N>", mynew)
top.bind("<Control-n>", mynew)
top.bind("<Control-O>", myopen)
top.bind("<Control-o>", myopen)
top.bind("<Control-S>", mysave)
top.bind("<Control-s>", mysave)
top.bind("<Control-Shift-S>", mysaveas)
top.bind("<Control-Shift-s>", mysaveas)
top.bind("<Button-3>", command)

windnd.hook_dropfiles(top,func=opened)

一些綁定,以及與opened相對應的事件判定。總而言之,都是和事件有關的一些東西。

啊,越講越上頭,超過了我預期的篇幅……好了,終於完結了!原本打算花一個月的,盡然一天就搞定了!這樣也好,畢竟作為一個初二學生,和電腦真的是……很沒有緣分。

最後,一段代碼送給我自己,也送給每一位讀者:

top.mainloop() #對於代碼是結束,對於程式僅僅是開始

完整的代碼:

# coding:utf-8
from tkinter import * from tkinter.filedialog import * from tkinter.messagebox import * import windnd import os import sys
kkk
=1
try: filename = sys.argv[1] except: filename = ""

def encryption(c, d): c = list(c + d) g=list(d) d=0 for i in g: d*=ord(i) d=round(abs(d)**0.5) f="0x" for i in c: e=str(ord(i)+d) d=round(300*(d**0.5)) f=f+e+"a" f=eval(f[:-1]) return (f)
def decrypt(c,d): c=hex(int(c)) print(c) c=c[2:].split("a") z=d g = list(d) d = 0 for i in g: d *= ord(i) d = round(abs(d) ** 0.5) f="" for i in c: e = chr(int(i)-d) d = round(300 * (d ** 0.5)) f = f + e if f[-len(z):]==z: f=f[:-len(z)] return (f) else: c="bbc"+12
def mynew(aaa=1): global top, filename, textPad top.title("無標題 - 加密文本編輯器") filename = None textPad.delete(1.0, END) textPad.insert(1.0, "")
def myopen(aaa=1): global filename,kkk filename = askopenfilename() if filename == "": filename = None else: top.title(os.path.basename(filename)+" - 加密文本編輯器") format=os.path.basename(filename)[os.path.basename(filename).find(".")+1:] textPad.delete(1.0, END) try: f = open(filename, 'rb') c = f.read() ccc = str(c)[2:-1] ccc.replace("\\","") textPad.insert(1.0,decrypt(ccc,format)) kkk=1 except: f.close() try: f = open(filename, 'r', encoding="gbk") try: c = f.read() except: f.close() f = open(filename, 'r', encoding="utf-8") c = f.read() textPad.insert(1.0, c) kkk = 0 except: f.close() f = open(filename, 'rb') c = f.read() textPad.insert(1.0, c) kkk=0 f.close()
def mysave(aaa=1): global filename,kkk try: msg = textPad.get(1.0, 'end')[0:-1] if kkk==0: f = open(filename, 'w', encoding="utf-8")
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • springboot自動裝配原理探究 結論: SpringBoot啟動會載入大量的自動配置類 我們看我們需要的功能有沒有在SpringBoot預設寫好的自動配置類當中; 我們再來看這個自動配置類中到底配置了哪些組件;(只要我們要用的組件存在在其中,我們就不需要再手動配置了) 給容器中自動配置類添加組 ...
  • vscode 中配置Java環境 轉載說明:本篇文檔原作者[@火星動力猿],文檔出處來自嗶哩嗶哩-【教程】VScode中配置Java運行環境 轉載請在開頭或顯眼位置標註轉載信息。 1.下載VScode 官網地址:https://code.visualstudio.com/ (點鏈接時按下Ctrl,不 ...
  • SpringMVC 是基於 MVC 開發模式的框架,用來優化控制器,是 Spring 家族的一員,同時它也具備 IOC 和 AOP ...
  • 一、填空題 在種群增長預測問題中,若資源環境等因素是有限的,則應使用的微分方程模型為 Logistic模型 某種群分為 4 個年齡組, 各組的繁殖率分別為 0, 0.8, 1.8, 0.2, 存活率分別為 0.5, 0.7, 0.9, 0. 現各組的數量均為 100, 則該種群的的穩定分佈向量為 解 ...
  • 一、Postman Postman 是一個款 HTTP 請求模擬工具 首先演示一下 Postman 最基本的使用,創建一個 Spring Boot 項目,測試的代碼如下: import org.springframework.web.bind.annotation.GetMapping; impor ...
  • ## 進程與線程的區別 - 進程基本上相互獨立的,而線程存在於進程內,是進程的一個子集 - 進程擁有共用的資源,如記憶體空間等,供其內部的線程共用 - 進程間通信較為複雜 - 同一臺電腦的進程通信稱為 IPC(Inter-process communication) - 不同電腦之間的進程... ...
  • 哈工大軟體構造Lab2中Assert的使用總結,可供後來學子借鑒學習 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...