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]))