吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 939|回复: 16
收起左侧

[Python 原创] 一个简单的RSA秘钥解析工具

  [复制链接]
aa008u 发表于 2024-12-11 10:47
在学习python的tkinter,然后就写一个有点无聊的RSA计算的小工具。
1、支持拖拽一个window下的.cer证书进去,自动解析;
2、可以随机生成RSA密钥对,然后进行加解密测试。
3、yafu分解是为了解决大数分解的问题,yafu工具可以分解,项目里没有yafu程序,只是模拟调用和返回结果的功能。如果要实现可自己下载yafu放在同级目录下,或者自己改一下代码中的路径。
4、用来很多三方库,需要自己安装一下:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pycryptodome libnum windnd rsa

界面

界面

RSA算法是一种非对称加密算法,它依赖于数学上的大数分解难题。RSA算法的公式和步骤如下:
  • 选择两个不同的大质数 p 和 q。
  • 计算这两个质数的乘积 n = pq。n 的长度(比特位数)就是密钥长度。
  • 计算欧拉函数 φ(n) = (p-1)(q-1)。φ(n) 是小于 n 且与 n 互质的正整数个数。
  • 选择一个整数 e,满足 1 < e < φ(n),并且 e 与 φ(n) 互质。e 和 n 将构成公钥
  • 计算 d,d 是 e 关于 φ(n) 的模反元素,即 d 满足 de ≡ 1 (mod φ(n))。d 和 n 将构成私钥
加密和解密过程使用以下公式:
  • 加密消息 M 得到密文 C:C=Memod&#8201;&#8201;nC=Memodn
  • 解密密文 C 得到明文 M:M=Cdmod&#8201;&#8201;nM=Cdmodn


[Python] 纯文本查看 复制代码
from Crypto.PublicKey import RSA
import tkinter as tk
from tkinter import messagebox,ttk,filedialog
import libnum
from Crypto.Util.number import *
import base64
import windnd
import os
import rsa

class Application(tk.Frame):
    def __init__(self, root):
        super().__init__(root)
        self.master = root
        self.key_file=''
        self.pack()
        self.fmt_var = tk.StringVar()
        self.master.geometry("700x600+100+50")
        # 设置窗口最小和最大尺寸
        self.master.minsize(700, 600)
        self.master.title("RSA秘钥解析")
        self.intWind()

    # 设置Text内容的函数
    def setText(self, text, s):
        text.delete(0.0, 'end')
        text.insert(0.0, s)

    # 解析RSA密钥
    def dec_key(self):
        # 从框中获取到RSA密钥字符串
        rsakey = self.key_text.get(0.0, 'end').strip()
        try:
            # 导入字符串的字节码,获取解析后的key
            key = RSA.importKey(rsakey.encode())
            if (key.has_private()):
                self.setText(self.type, "私钥")
                self.setText(self.bits, str(key.size_in_bits()) + "位")
                self.setText(self.e_text, key.e)
                self.e = key.e
                self.setText(self.n_text, key.n)
                self.n = key.n
                self.setText(self.d_text, key.d)
                self.d = key.d
                self.setText(self.p_text, key.p)
                self.setText(self.q_text, key.q)
                self.setText(self.phi_text, (key.p - 1) * (key.q - 1))
            else:
                self.setText(self.type, "公钥")
                self.setText(self.bits, str(key.size_in_bits()) + "位")
                self.setText(self.e_text, key.e)
                self.e = key.e
                self.setText(self.n_text, key.n)
                self.n = key.n
        except:
            messagebox.showinfo("提示", "不是标准的密钥")

    # 拖拽密钥文件解析
    def draw_key(self,files):
        self.key_file=files[0].decode('gbk')
        self.importKey()

    # 导入二进制的密钥文件解析
    def importKey(self):
        if self.key_file!='':
            path_=self.key_file
        else:
            path_=filedialog.askopenfilename()
        with open(path_,'rb') as f:
            rsakey=f.read()
        try:
            # 导入字符串的字节码,获取解析后的key
            key=RSA.importKey(rsakey)
            if (key.has_private()):
                if b'---' in rsakey:
                    self.setText(self.key_text,rsakey.decode())
                else:
                    self.setText(self.key_text, "-----BEGIN RSA PRIVATE KEY-----\n" + base64.b64encode(
                        rsakey).decode() + "\n-----END RSA PRIVATE KEY-----")
                self.setText(self.type, "私钥")
                self.setText(self.bits, str(key.size_in_bits()) + "位")
                self.setText(self.e_text, key.e)
                self.e = key.e
                self.setText(self.n_text, key.n)
                self.n = key.n
                self.setText(self.d_text, key.d)
                self.d = key.d
                self.setText(self.p_text, key.p)
                self.setText(self.q_text, key.q)
                self.setText(self.phi_text, (key.p - 1) * (key.q - 1))
            else:
                if b'---' in rsakey:
                    self.setText(self.key_text,rsakey.decode())
                else:
                    self.setText(self.key_text, "-----BEGIN PUBLIC KEY-----\n" + base64.b64encode(
                        rsakey).decode() + "\n-----END PUBLIC KEY-----")
                self.setText(self.type, "公钥")
                self.setText(self.bits, str(key.size_in_bits()) + "位")
                self.setText(self.e_text, key.e)
                self.e = key.e
                self.setText(self.n_text, key.n)
                self.n = key.n
        except:
            messagebox.showinfo("提示", "不是标准的密钥")

    # 明文加密方法
    def enc_txt(self):
        if self.fmt_var.get() == "16进制":
            e = int(self.e_text.get(0.0, 'end').strip(), 16)
            n = int(self.n_text.get(0.0, 'end').strip(), 16)
            c = self.c_text.get(0.0, 'end').strip()
            c = c.encode("utf-8")
            pubkey=rsa.key.PublicKey(n,e)
            m = rsa.encrypt(c,pubkey)
            self.setText(self.m_text, base64.b64encode(m))
        elif self.fmt_var.get() == "10进制":
            e = int(self.e_text.get(0.0, 'end').strip())
            n = int(self.n_text.get(0.0, 'end').strip())
            c = self.c_text.get(0.0, 'end').strip()
            c = c.encode("utf-8")
            pubkey=rsa.key.PublicKey(n,e)
            m = rsa.encrypt(c,pubkey)
            self.setText(self.m_text, base64.b64encode(m))
        else:
            return 0

    # 密文解密方法
    def dec_txt(self):
        if self.fmt_var.get() == "16进制":
            n = int(self.n_text.get(0.0, 'end').strip(), 16)
            d = int(self.d_text.get(0.0, 'end').strip(), 16)
            e = int(self.e_text.get(0.0, 'end').strip(), 16)
            p = int(self.p_text.get(0.0, 'end').strip(), 16)
            q = int(self.q_text.get(0.0, 'end').strip(), 16)
            m = self.m_text.get(0.0, 'end').strip()
            privkey=rsa.key.PrivateKey(n,e,d,p,q)
            c=rsa.decrypt(base64.b64decode(m),privkey).decode("utf-8")
            self.setText(self.c_text, c)
        elif self.fmt_var.get() == "10进制":
            n = int(self.n_text.get(0.0, 'end').strip())
            d = int(self.d_text.get(0.0, 'end').strip())
            e = int(self.e_text.get(0.0, 'end').strip())
            p = int(self.p_text.get(0.0, 'end').strip())
            q = int(self.q_text.get(0.0, 'end').strip())
            m = self.m_text.get(0.0, 'end').strip()
            privkey=rsa.key.PrivateKey(n,e,d,p,q)
            c=rsa.decrypt(base64.b64decode(m),privkey).decode("utf-8")
            self.setText(self.c_text, c)
        else:
            return 0

    # 清除所有框里的内容
    def clear(self):
        self.key_text.delete(0.0, 'end')
        self.type.delete(0.0, 'end')
        self.bits.delete(0.0, 'end')
        self.e_text.delete(0.0, 'end')
        self.n_text.delete(0.0, 'end')
        self.d_text.delete(0.0, 'end')
        self.p_text.delete(0.0, 'end')
        self.q_text.delete(0.0, 'end')
        self.phi_text.delete(0.0, 'end')
        self.c_text.delete(0.0, 'end')
        self.m_text.delete(0.0, 'end')

    # 格式转换计算方法
    def int_format(self, *args):
        e = self.e_text.get(0.0, 'end').strip()
        if e == '': e = '0'
        n = self.n_text.get(0.0, 'end').strip()
        if n == '': n = '0'
        d = self.d_text.get(0.0, 'end').strip()
        if d == '': d = '0'
        p = self.p_text.get(0.0, 'end').strip()
        if p == '': p = '0'
        q = self.q_text.get(0.0, 'end').strip()
        if q == '': q = '0'
        phi = self.phi_text.get(0.0, 'end').strip()
        if phi == '': phi = '0'
        m = self.m_text.get(0.0, 'end').strip()
        if m == '': m = '0'
        if self.fmt_var.get() == "16进制":
            self.setText(self.e_text, hex(int(e)))
            self.setText(self.n_text, hex(int(n)))
            self.setText(self.d_text, hex(int(d)))
            self.setText(self.p_text, hex(int(p)))
            self.setText(self.q_text, hex(int(q)))
            self.setText(self.phi_text, hex(int(phi)))
            self.setText(self.m_text, hex(int(m)))

        if self.fmt_var.get() == "10进制":
            self.setText(self.e_text, int(e, 16))
            self.setText(self.n_text, int(n, 16))
            self.setText(self.d_text, int(d, 16))
            self.setText(self.p_text, int(p, 16))
            self.setText(self.q_text, int(q, 16))
            self.setText(self.phi_text, int(phi, 16))
            self.setText(self.m_text, int(m, 16))

    # 根据p、q计算出密钥其他参数
    def calc_key(self):
        if self.fmt_var.get() == "16进制":
            p = int(self.p_text.get(0.0, 'end').strip(), 16)
            q = int(self.q_text.get(0.0, 'end').strip(), 16)
            e = self.e_text.get(0.0, 'end').strip()
            # 如果e没有设置则默认为65537
            if e == '':
                e = 65537
            else:
                e = int(e, 16)
            n = p * q
            phi = (p - 1) * (q - 1)
            # ed=1 mod phi 计算d
            d = libnum.invmod(e, phi)
            self.setText(self.e_text, hex(e))
            self.setText(self.n_text, hex(n))
            self.setText(self.d_text, hex(d))
            self.setText(self.phi_text, hex(phi))
        elif self.fmt_var.get() == "10进制":
            p = int(self.p_text.get(0.0, 'end').strip())
            q = int(self.q_text.get(0.0, 'end').strip())
            e = self.e_text.get(0.0, 'end').strip()
            if e == '':
                e = 65537
            else:
                e = int(e)
            n = p * q
            phi = (p - 1) * (q - 1)
            d = libnum.invmod(e, phi)
            self.setText(self.e_text, e)
            self.setText(self.n_text, n)
            self.setText(self.d_text, d)
            self.setText(self.phi_text, phi)

    # 根据给定的密钥位数随机生成密钥
    def geno_key(self):
        if self.fmt_var.get() == "16进制":
            bits = self.bits.get(0.0, 'end').strip()
            e = self.e_text.get(0.0, 'end').strip()
            if bits == '':
                bits = 1024
                self.setText(self.bits, bits)
            else:
                bits = int(bits)
            if e == '' or '0x0':
                e = 65537
            else:
                e = int(e, 16)
            # 这里使用Crypto.Util.number.getPrime(n)也可以使用libnum.generate_prime(n)
            p = getPrime(bits)
            q = getPrime(bits)
            n = p * q
            phi = (p - 1) * (q - 1)
            # 这里使用libnum.invmod()也可以使用 Crypto.Util.number.inverse()
            d = libnum.invmod(e, phi)
            self.setText(self.e_text, hex(e))
            self.setText(self.n_text, hex(n))
            self.setText(self.d_text, hex(d))
            self.setText(self.p_text, hex(p))
            self.setText(self.q_text, hex(q))
            self.setText(self.phi_text, hex(phi))
        elif self.fmt_var.get() == "10进制":
            bits = self.bits.get(0.0, 'end').strip()
            e = self.e_text.get(0.0, 'end').strip()
            if bits == '':
                bits = 1024
                self.setText(self.bits, bits)
            else:
                bits = int(bits)
            if e == '' or '0':
                e = 65537
            else:
                e = int(e)
            p = getPrime(bits)
            q = getPrime(bits)
            n = p * q
            phi = (p - 1) * (q - 1)
            d = libnum.invmod(e, phi)
            self.setText(self.e_text, e)
            self.setText(self.n_text, n)
            self.setText(self.d_text, d)
            self.setText(self.p_text, p)
            self.setText(self.q_text, q)
            self.setText(self.phi_text, phi)

    # 分解N计算
    def calc_N(self):
        N=self.n_text2.get(0.0,'end').strip()
        jg=''
        t = os.popen(r"yafu-x64.exe factor({})".format(N)).readlines()
        for i in t:
            if i.startswith('P'):
                jg=jg+'\n'+i.strip()
        self.setText(self.jg_text2,jg.strip())

    # 重新创建一个界面
    def creatwindow(self):
        # 重新船舰一个界面,上层是master界面
        newwindow=tk.Toplevel(self.master)
        # 设置新界面的标题
        newwindow.title("N分解计算")
        # 设置新界面的大小和偏移
        newwindow.geometry("620x300+120+60")
        # 在新界面上创建一个UI框架
        N_frame = tk.Frame(newwindow)
        tk.Label(N_frame, text="  n:").grid(row=0, column=0, pady=5)
        self.n_text2 = tk.Text(N_frame, height=5, bg="#e3f9fd")
        self.n_text2.grid(row=0, column=1, pady=5)
        tk.Label(N_frame, text="结果:").grid(row=1, column=0, pady=5)
        self.jg_text2 = tk.Text(N_frame, height=10, bg="#e3f9fd")
        self.jg_text2.grid(row=1, column=1, pady=5)
        N_frame.pack()
        B_frame=tk.Frame(newwindow)
        ttk.Button(B_frame, text="分解N", command=self.calc_N).grid(row=1, column=0, padx=10)
        B_frame.pack()

    # 设置UI布局
    def intWind(self):
        key_frame = tk.Frame(self)
        tk.Label(key_frame, text="证书内容:").grid(row=0, column=0, pady=10)
        tk.Button(key_frame, text="导入解析", command=self.importKey).grid(row=1, column=0)

        self.key_text = tk.Text(key_frame, height=5)
        self.key_text.grid(row=0, column=1, pady=10,rowspan=7)
        key_frame.pack(anchor='w')
        # 通过拖拽文件到key_fram组件处进行解析
        windnd.hook_dropfiles(key_frame,func=self.draw_key)

        type_frame = tk.Frame(self)
        tk.Label(type_frame, text="证书类型:").grid(row=0, column=0, pady=5)
        self.type = tk.Text(type_frame, height=1, width=6, bg="#bababa")
        self.type.grid(row=0, column=1, pady=5)
        tk.Label(type_frame, text="  ").grid(row=0, column=2, pady=5)
        tk.Label(type_frame, text="证书位数:").grid(row=0, column=3, pady=5)
        self.bits = tk.Text(type_frame, height=1, width=6, bg="#bababa")
        self.bits.grid(row=0, column=4, pady=5)
        tk.Label(type_frame, text="  ").grid(row=0, column=5, pady=5)
        tk.Label(type_frame, text="进制:").grid(row=0, column=6, pady=5)
        # 增加一个下拉选择框
        self.fmt = ttk.Combobox(type_frame, textvariable=self.fmt_var, width=10)
        # 设置下拉框的选项
        self.fmt['value'] = ('10进制', '16进制')
        # 设置下拉框的默认选项
        self.fmt.current(0)
        # 当下拉框内容变化是绑定一个方法
        self.fmt.bind('<<ComboboxSelected>>', self.int_format)
        self.fmt.grid(row=0, column=7, pady=5)
        type_frame.pack(anchor='w')

        e_frame = tk.Frame(self)
        tk.Label(e_frame, text="          e:").grid(row=0, column=0, pady=5)
        self.e_text = tk.Text(e_frame, height=1, bg="#e3f9fd")
        self.e_text.grid(row=0, column=1, pady=5)
        e_frame.pack(anchor='w')

        n_frame = tk.Frame(self)
        tk.Label(n_frame, text="          n:").grid(row=0, column=0, pady=5)
        self.n_text = tk.Text(n_frame, height=3, bg="#e3f9fd")
        self.n_text.grid(row=0, column=1, pady=5)
        n_frame.pack(anchor='w')

        d_frame = tk.Frame(self)
        tk.Label(d_frame, text="          d:").grid(row=0, column=0, pady=5)
        self.d_text = tk.Text(d_frame, height=3, bg="#a98175")
        self.d_text.grid(row=0, column=1, pady=5)
        d_frame.pack(anchor='w')

        p_frame = tk.Frame(self)
        tk.Label(p_frame, text="          p:").grid(row=0, column=0, pady=5)
        self.p_text = tk.Text(p_frame, height=3, bg="#bababa")
        self.p_text.grid(row=0, column=1, pady=5)
        p_frame.pack(anchor='w')

        q_frame = tk.Frame(self)
        tk.Label(q_frame, text="          q:").grid(row=0, column=0, pady=5)
        self.q_text = tk.Text(q_frame, height=3, bg="#bababa")
        self.q_text.grid(row=0, column=1, pady=5)
        q_frame.pack(anchor='w')

        phi_frame = tk.Frame(self)
        tk.Label(phi_frame, text="    phi(n):").grid(row=0, column=0, pady=5)
        self.phi_text = tk.Text(phi_frame, height=3, bg="#bababa")
        self.phi_text.grid(row=0, column=1, pady=5)
        phi_frame.pack(anchor='w')

        c_frame = tk.Frame(self)
        tk.Label(c_frame, text="      明文:").grid(row=0, column=0, pady=5)
        self.c_text = tk.Text(c_frame, height=3)
        self.c_text.grid(row=0, column=1, pady=5)
        c_frame.pack(anchor='w')

        m_frame = tk.Frame(self)
        tk.Label(m_frame, text="      密文:").grid(row=0, column=0, pady=5)
        self.m_text = tk.Text(m_frame, height=3)
        self.m_text.grid(row=0, column=1, pady=5)
        m_frame.pack(anchor='w')

        btn_frame = tk.Frame(self)
        ttk.Button(btn_frame, text="解密证书", command=self.dec_key).grid(row=0, column=0, padx=10)
        ttk.Button(btn_frame, text="用pq计算秘钥", command=self.calc_key).grid(row=0, column=1, padx=10)
        ttk.Button(btn_frame, text="明文加密", command=self.enc_txt).grid(row=0, column=2, padx=10)
        ttk.Button(btn_frame, text="密文解密", command=self.dec_txt).grid(row=0, column=3, padx=10)
        ttk.Button(btn_frame, text="随机生成秘钥", command=self.geno_key).grid(row=0, column=4, padx=10)
        ttk.Button(btn_frame, text="清空", command=self.clear).grid(row=0, column=5, padx=10)
        ttk.Button(btn_frame, text="yafu分解N", command=self.creatwindow).grid(row=1, column=0, padx=10,pady=10)
        btn_frame.pack()


if __name__ == "__main__":
    root = tk.Tk()
    app = Application(root)
    app.mainloop()

免费评分

参与人数 3吾爱币 +9 热心值 +2 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
BTCQAQ + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
zhczf + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Xiaosesi 发表于 2024-12-11 11:09
这个需要什么版本运行呢?
 楼主| aa008u 发表于 2024-12-11 11:11
xianggua 发表于 2024-12-11 11:52
wwdxs 发表于 2024-12-11 12:16
感谢楼主分享
pizazzboy 发表于 2024-12-11 14:31
感谢楼主分享
xiaoli521 发表于 2024-12-11 14:52
感谢版主
BTCQAQ 发表于 2024-12-11 15:11
感谢大佬热心分享,我好好学习一下
Seaink 发表于 2024-12-11 15:17
感谢分享,找机会试一下
CQGaxm 发表于 2024-12-11 15:36
感谢楼主分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-1-6 05:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表