当前位置:首页>python>用 Python 写一个轻量级密码生成器,一键生成复杂密码

用 Python 写一个轻量级密码生成器,一键生成复杂密码

  • 2026-10-11 08:31:06
用 Python 写一个轻量级密码生成器,一键生成复杂密码

每次注册新账号,相信很多小伙伴们会在“123456”、“生日+姓名”和“记不住的乱码”之间反复妥协。今天,我们来用 Python 标准库实现一个真正具备密码学安全性的密码生成器。代码大约 80 行,零第三方依赖,界面简洁,开箱即用,效果如下。


一、为什么不能用 random 生成密码?

Python 的 random 模块底层使用 Mersenne Twister 算法。它是一种高质量的伪随机数生成器,适用于模拟、游戏或抽样,但不是加密安全的。它的内部状态在足够多的输出后是可预测的,攻击者一旦捕获部分输出,就有可能推演出后续生成的“随机”密码。

Python 3.6 引入了 secrets 模块,它直接调用操作系统底层的 CSPRNG(加密安全伪随机数生成器,如 Linux 的 /dev/urandom、Windows 的 CryptGenRandom)。专为密钥、Token、密码等安全场景设计,不可预测、不可重现。因此生成密码,请始终使用 secrets。


二、代码结构与核心设计

1. 纯标准库,跨平台运行

仅依赖 tkinter、string、secrets,无需 pip install。Windows、macOS、Linux 均可直接执行。

2. 动态字符池构建

通过复选框状态动态拼接 string.ascii_uppercase、string.digits 等常量。避免硬编码符号集,也方便后续扩展(如剔除易混淆字符 O0l1I)。

3. 安全的生成逻辑

password = ''.join(secrets.choice(pool) for _ in range(length))

使用生成器表达式配合 secrets.choice,在密码学安全的字符池中均匀采样。长度由用户控制,默认 12 位,建议 ≥12。

4. 剪贴板交互的细节处理

self.root.clipboard_clear()self.root.clipboard_append(pwd)self.root.update()  # 关键:确保部分系统成功写入

tkinter 的剪贴板操作在 macOS 和部分 Linux 桌面环境下是异步的。调用 root.update() 可强制刷新事件循环,避免“复制了但粘贴为空”的偶发问题。按钮提供 1.2 秒视觉反馈,交互更自然。


三、完整代码

可直接运行

import tkinter as tkfrom tkinter import messageboximport stringimport secretsclass PasswordGenerator:    def __init__(self, root):        self.root = root        self.root.title("🔐 强密码生成器")        self.root.geometry("420x300")        self.root.resizable(False, False)        self.length_var = tk.IntVar(value=12)        self.upper_var = tk.BooleanVar(value=True)        self.lower_var = tk.BooleanVar(value=True)        self.digits_var = tk.BooleanVar(value=True)        self.symbols_var = tk.BooleanVar(value=False)        self.result_var = tk.StringVar()        self._setup_ui()    def _setup_ui(self):        main = tk.Frame(self.root, padx=20, pady=15)        main.pack(fill=tk.BOTH, expand=True)        tk.Label(main, text="自定义密码生成器", font=("Arial", 14, "bold")).pack(pady=(0, 10))        len_frm = tk.Frame(main)        len_frm.pack(fill=tk.X, pady=5)        tk.Label(len_frm, text="密码长度:").pack(side=tk.LEFT)        tk.Spinbox(len_frm, from_=4, to=32, textvariable=self.length_var, width=5, font=("Consolas", 10)).pack(side=tk.LEFT, padx=5)        chk_frm = tk.Frame(main)        chk_frm.pack(fill=tk.X, pady=5)        tk.Checkbutton(chk_frm, text="大写字母 A-Z", variable=self.upper_var).pack(side=tk.LEFT, padx=5)        tk.Checkbutton(chk_frm, text="小写字母 a-z", variable=self.lower_var).pack(side=tk.LEFT, padx=5)        tk.Checkbutton(chk_frm, text="数字 0-9", variable=self.digits_var).pack(side=tk.LEFT, padx=5)        tk.Checkbutton(chk_frm, text="特殊符号 !@#", variable=self.symbols_var).pack(side=tk.LEFT, padx=5)        tk.Button(main, text="🔑 生成密码", command=self.generate,                   bg="#4CAF50", fg="white", font=("Arial", 10, "bold")).pack(fill=tk.X, pady=15)        res_frm = tk.Frame(main)        res_frm.pack(fill=tk.X)        tk.Entry(res_frm, textvariable=self.result_var, state="readonly",                  font=("Consolas", 12), justify="center").pack(side=tk.LEFT, fill=tk.X, expand=True)        self.copy_btn = tk.Button(res_frm, text="📋 复制", command=self.copy_pwd, width=10)        self.copy_btn.pack(side=tk.RIGHT, padx=(5, 0))    def generate(self):        pool = ""        if self.upper_var.get(): pool += string.ascii_uppercase        if self.lower_var.get(): pool += string.ascii_lowercase        if self.digits_var.get(): pool += string.digits        if self.symbols_var.get(): pool += string.punctuation        if not pool:            messagebox.showwarning("提示", "请至少勾选一种字符类型!")            return        length = self.length_var.get()        password = ''.join(secrets.choice(pool) for _ in range(length))        self.result_var.set(password)        self.copy_btn.config(text="📋 复制")    def copy_pwd(self):        pwd = self.result_var.get()        if not pwd:            messagebox.showinfo("提示", "请先生成密码")            return        self.root.clipboard_clear()        self.root.clipboard_append(pwd)        self.root.update()        self.copy_btn.config(text="✅ 已复制", bg="#2196F3", fg="white")        self.root.after(1200, lambda: self.copy_btn.config(text="📋 复制", bg="SystemButtonFace", fg="black"))if __name__ == "__main__":    root = tk.Tk()    app = PasswordGenerator(root)    root.mainloop()

过往文章
Python编程小技巧--用Python查询天气
Python可视化 | 无需游戏引擎,用 tkinter 手写一个物理模拟器
Python 图形界面入门:一个能自动录屏的 2048 游戏
Python编程基础算法--斐波那契数列的矩阵算法
优质科普书推荐 | 《微积分的力量》:在流动的世界里,寻找不变的锚
Python 库巡礼 | Flask:以简驭繁的 Web 构建哲学
最速降线:比直线更快的曲线
Python与办公自动化--批量生成报告/通知
计算机科学人物志 | 匈牙利算法:二分图匹配的百年寻踪
VS Code插件观察 | Rainbow Brackets:括号着色与认知负荷的优化
过往合集
Python--数据/图像可视化
Python编程基础算法
Python编程小技巧
细数那些经典教材
Python库巡礼
Python与数学之美
Python与办公自动化
计算机科学人物志
VS Code插件观察

最新文章

随机文章