Python筆記:帶路黨可用的公用信道加密工具(rsa+rc4)
- 2019 年 11 月 22 日
- 筆記
應該如何保障資訊安全呢?
使用PGP或者GPG是很好的方法。但是,本著DIY精神,今天在網上東拼西湊了一個基於RC4和RSA的加密工具(玩具)。
1 用法
使用在前需要生成密鑰對。使用generateKeys.py生成。對方的公鑰保存到keys文件夾,自己的私鑰保存到項目根目錄。
rsa加密相互使用對方的公鑰對原文加密,把密文傳輸到對方,由對方使用配套的私鑰進行解密。如果要雙方能相互通訊,則必須互相擁有對方的公鑰。
加密
1 雙擊main.pyw,出現窗口。
2 將要加密的字元串如「今天天氣真好」,ctrl + c 複製到剪貼板。
3 激活main.pyw窗口,按快捷鍵shitf + x。
4 此時窗口閃動一長串字元串,很快又變成原字元串「今天天氣真好」。這意味著密文已經生成成功了。並且保存到了剪貼板。
5 到需要發送的地方如微信或者郵件,按ctrl + v。此時將粘貼一大串密文。發送給對端即可。
解密
雙擊main.pyw 出現窗口。
把密文ctrl + c 複製到剪貼板。
如果你有許可權,被解密的原文自動出現在main.pyw窗口中。(也可以使用shift + v快捷鍵)
配置
settings.py
email用來配置你自己的私鑰郵件地址。用來解密用。
usermaps 用來配置發送的密文能被誰解密。注意,keys文件夾下必須有對應的公鑰。
下載

2 文件組織如下:
D:.
│ cryptObj.py
│ generatekey.py
│ main.pyw
│ settings.py
│ test.py
│
├─bll
│ encrypt.py
│ rc4.py
│ __init__.py
└─keys
3 程式碼
main.pyw
#coding:utf-8 import time import Tkinter as tk from bll import encrypt as enc import cryptObj import thread import time class MainApplication(tk.Frame): def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent S = tk.Scrollbar(root) T = tk.Text(root, height=4) S.pack(side=tk.RIGHT, fill=tk.Y) T.pack(side=tk.LEFT, fill=tk.Y) S.config(command=T.yview) T.config(yscrollcommand=S.set) self.MainText = T parent.bind("<Shift-Key-X>",self.EncryptClipBoard) parent.bind("<Shift-Key-V>",self.DecryptClipBoard) self.MainText.pack() thread.start_new_thread (self.monitor_clipboard,()) def EncryptClipBoard(self,event): clip_text = self.parent.clipboard_get() msg = cryptObj.Messages(clip_text) clip_text = msg.ToString() self.MainText.delete('1.0', tk.END) self.MainText.insert(1.0,clip_text) self.parent.clipboard_clear() self.parent.clipboard_append(clip_text) def DecryptClipBoard(self,event): clip_text = self.parent.clipboard_get() msg = cryptObj.Messages(clip_text) clip_text = msg.DecryptJson() self.MainText.delete('1.0', tk.END) self.MainText.insert(1.0,clip_text) self.parent.clipboard_clear() self.parent.clipboard_append(clip_text) def monitor_clipboard(self): oldstr = "" while True: time.sleep(1) clip_text = self.parent.clipboard_get() if isinstance(clip_text,str) and oldstr != clip_text: if clip_text.startswith('{"userpwd'): oldstr = clip_text msg = cryptObj.Messages(clip_text) clip_text = msg.DecryptJson() self.MainText.delete('1.0', tk.END) self.MainText.insert(1.0,clip_text) if __name__ == "__main__": root=tk.Tk() root.geometry("600x400") main = MainApplication(root) main.pack(side="top", fill="both", expand=True) root.mainloop()settings.py
#coding:utf-8 email = "[email protected]" usermaps = ["[email protected]","[email protected]"]
generatekey.py
#coding:utf-8 import rsa email = raw_input("input email:") # 先生成一對密鑰,然後保存.pem格式文件,當然也可以直接使用 pubkey, privkey = rsa.newkeys(1024) pub = pubkey.save_pkcs1() with open(email+'-pub.pem', 'w') as f: f.write(pub) pri = privkey.save_pkcs1() with open(email+'-pri.pem', 'w') as f: f.write(pri)cryptObj.py
#coding:utf-8 from bll import encrypt as enc from bll import rc4 import os import settings import json import base64 class Messages(object): def __init__(self,msg): self.UserMaps = settings.usermaps self.Message = msg def GetRndStr(self): rndByte = os.urandom(6) b64Str = base64.urlsafe_b64encode(rndByte) return b64Str def ToString(self): rndpwd = self.GetRndStr() class TempMsgs(object): pass msg = TempMsgs() msg.userpwd = {} for k in self.UserMaps: msg.userpwd[k] = enc.EncryptRsa(rndpwd,k) rc4enc = rc4.rc4(rndpwd) msg.value = rc4enc.encode(self.Message) jsons = json.dumps(msg.__dict__) return jsons def DecryptJson(self): jsons = json.loads(self.Message) userpwds = jsons['userpwd'] encValue = jsons["value"] for k in userpwds: if k == settings.email: encpwd = userpwds[k] rndpwd = enc.DecryptRsa(encpwd,k) rc4enc = rc4.rc4(rndpwd) return rc4enc.decode(encValue) return ""bll/encrypt.py
#coding:utf-8 import settings import rsa import base64 main_email = settings.email dirname = "keys/" # 用公鑰加密、再用私鑰解密 def EncryptRsa(text,email): with open(dirname + email + '-pub.pem') as publickfile: p = publickfile.read() pubkey = rsa.PublicKey.load_pkcs1(p) crypto = rsa.encrypt(text, pubkey) b64Str = base64.urlsafe_b64encode(crypto) return b64Str def DecryptRsa(crypto,email): with open(email + '-pri.pem') as privatefile: p = privatefile.read() privkey = rsa.PrivateKey.load_pkcs1(p) text = base64.urlsafe_b64decode(str(crypto)) return rsa.decrypt(text, privkey)
bll/rc4.py
#coding=utf-8 import sys,os,hashlib,time,base64 class rc4: def __init__(self,public_key = None,ckey_lenth = 16): self.ckey_lenth = ckey_lenth self.public_key = public_key or 'none_public_key' key = hashlib.md5(self.public_key).hexdigest() self.keya = hashlib.md5(key[0:16]).hexdigest() self.keyb = hashlib.md5(key[16:32]).hexdigest() self.keyc = '' def encode(self,string): string = string.encode('utf-8') self.keyc = hashlib.md5(str(time.time())).hexdigest()[32 - self.ckey_lenth:32] string = '0000000000' + hashlib.md5(string + self.keyb).hexdigest()[0:16] + string self.result = '' self.docrypt(string) return self.keyc + base64.b64encode(self.result) def decode(self,string): self.keyc = string[0:self.ckey_lenth] string = base64.b64decode(string[self.ckey_lenth:]) self.result = '' self.docrypt(string) result = self.result if (result[0:10] == '0000000000' or int(result[0:10]) - int(time.time()) > 0) and result[10:26] == hashlib.md5(result[26:] + self.keyb).hexdigest()[0:16]: return result[26:] else: return None def docrypt(self,string): string_lenth = len(string) result = '' box = list(range(256)) randkey = [] cryptkey = self.keya + hashlib.md5(self.keya + self.keyc).hexdigest() key_lenth = len(cryptkey) for i in xrange(255): randkey.append(ord(cryptkey[i % key_lenth])) for i in xrange(255): j = 0 j = (j + box[i] + randkey[i]) % 256 tmp = box[i] box[i] = box[j] box[j] = tmp for i in xrange(string_lenth): a = j = 0 a = (a + 1) % 256 j = (j + box[a]) % 256 tmp = box[a] box[a] = box[j] box[j] = tmp self.result += chr(ord(string[i]) ^ (box[(box[a] + box[j]) % 256]))