背景介绍
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。
RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
由于学校作业的契机,写一一个关于RSA密钥生成、加解密的小代码,分享给大家一同学习。
其中运用了GUI交互库tkinter,这也是我第一次使用,感觉很有意思。希望在以后的日子里可以熟练掌握这个基本python库!
代码分享
import tkinter as tk
import math
from tkinter import messagebox
import random
class RSAApp:#构造函数,初始化
def __init__(self, root):
self.root = root
self.root.title("RSA 加解密")
self.main_menu()
def main_menu(self):#主菜单
self.clear_frame()
tk.Label(self.root, text="主菜单").pack(pady=10)
tk.Button(self.root, text="加密", command=self.encrypt_menu).pack(pady=5)
tk.Button(self.root, text="解密", command=self.decrypt_menu).pack(pady=5)
tk.Button(self.root, text="生成密钥", command=self.generate_keys_menu).pack(pady=5)
def encrypt_menu(self):
self.clear_frame()
tk.Label(self.root, text="输入明文").pack(pady=5)
self.plaintext_entry = tk.Entry(self.root, width=50)
self.plaintext_entry.pack(pady=5)
tk.Label(self.root, text="输入公钥 (e, n)").pack(pady=5)
self.public_key_entry = tk.Entry(self.root, width=50)
self.public_key_entry.pack(pady=5)
tk.Button(self.root, text="加密", command=self.encrypt).pack(pady=5)
tk.Button(self.root, text="返回", command=self.main_menu).pack(pady=5)
def decrypt_menu(self):
self.clear_frame()
tk.Label(self.root, text="输入密文").pack(pady=5)
self.ciphertext_entry = tk.Entry(self.root, width=50)
self.ciphertext_entry.pack(pady=5)
tk.Label(self.root, text="输入私钥 (d, n)").pack(pady=5)
self.private_key_entry = tk.Entry(self.root, width=50)
self.private_key_entry.pack(pady=5)
tk.Button(self.root, text="解密", command=self.decrypt).pack(pady=5)
tk.Button(self.root, text="返回", command=self.main_menu).pack(pady=5)
def generate_keys_menu(self):
self.clear_frame()
tk.Label(self.root, text="生成的密钥对").pack(pady=5)
tk.Label(self.root, text="公钥 (e, n)").pack(pady=5)
self.public_key_text = tk.Text(self.root, height=5, width=50)
self.public_key_text.pack(pady=5)
tk.Label(self.root, text="私钥 (d, n)").pack(pady=5)
self.private_key_text = tk.Text(self.root, height=5, width=50)
self.private_key_text.pack(pady=5)
tk.Button(self.root, text="生成密钥", command=self.generate_keys).pack(pady=5)
tk.Button(self.root, text="返回", command=self.main_menu).pack(pady=5)
def encrypt(self):
try:
plaintext = int(self.plaintext_entry.get())
e, n = map(int, self.public_key_entry.get().split(','))
ciphertext = pow(plaintext, e, n)
messagebox.showinfo("加密结果", f"密文: {ciphertext}")
except Exception as e:
messagebox.showerror("错误", str(e))
def decrypt(self):
try:
ciphertext = int(self.ciphertext_entry.get())
d, n = map(int, self.private_key_entry.get().split(','))
plaintext = pow(ciphertext, d, n)
messagebox.showinfo("解密结果", f"明文: {plaintext}")
except Exception as e:
messagebox.showerror("错误", str(e))
def generate_keys(self):
p = self.generate_prime()#生成素数
q = self.generate_prime()
n = p * q
phi = (p - 1) * (q - 1)
e=random.choice([65557,65587,65609,65617,65629,65647,65651,65657,65677,65687,65701,65707,65713,65717,65719,65729,65731,65761,65777,65789]) #公钥指数
d = self.modinv(e, phi)
self.public_key_text.delete(1.0, tk.END)
self.private_key_text.delete(1.0, tk.END)
self.public_key_text.insert(tk.END, f"{e}, {n}")
self.private_key_text.insert(tk.END, f"{d}, {n}")
def generate_prime(self):
while True:
num = random.randint(100, 999)
if self.is_prime(num):
return num
def is_prime(self, num):
if num < 2:
return False
for i in range(2, int(num ** 0.5) + 1):
if num % i == 0:
return False
return True
def modinv(self, a, m):
# 扩展欧几里得算法求模逆
m0, x0, x1 = m, 0, 1
if m == 1:
return 0
while a > 1:
q = a // m
m, a = a % m, m
x0, x1 = x1 - q * x0, x0
if x1 < 0:
x1 += m0
return x1
def clear_frame(self):
for widget in self.root.winfo_children():
widget.destroy()
if __name__ == "__main__":
root = tk.Tk() #创建主窗口对象
app = RSAApp(root) #构造实例
root.mainloop()
结果示范
密钥生成
加密
解密