引言
这个工具十分简单,实现的功能就是根据字符集和密码长度生成一个密码字典
生成
首先,说到这个,我的思路就是传入一个长度的列表和字符集列表,再根据此输出一个密码源的列表.
要实现这个功能,itertools.combinations绝对是个不错的方法.
这个函数返回输入的可迭代对象中元素组成要求长度的子序列
很多人用IDE查看定义,却发现在一个pyi文件下,定义也很抽象,这是因为此模块在底层由C语言实现,代码在Modules/itertoolsmodule.c下可找到,用Python实现相当于(仅供参考)
def combinations(iterable, r):
pool = tuple(iterable)
n = len(pool)
if r > n:
return
indices = list(range(r))
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
return
indices[i] += 1
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
yield tuple(pool[i] for i in indices)
为了保证效率,我们这里直接用这个模块(from itertools import combinations)而不是使用以上的Python实现.
总之,我们可以得到一个初步的函数
def gen_word(length: int, charset: list) -> list:
strings = []
strings.extend(combinations(charset, length))
return ["".join(string) for string in strings]
这个函数获取了每个长度对应的字符串列表
接着,我们用for循环就可以简单地实现我们想要的功能了
def gen(length: list, charset: list) -> list:
password_list = []
for l in range(1, len(length) + 1):
password = gen_word(l, charset)
password_list.extend(password)
return password_list
代码很易懂不解释了
GUI
写完了核心功能,剩下就能随意自定义了,我这边写了个简单的GUI,仅供参考
import string
import tkinter as tk
import tkinter.filedialog as filedialog
import tkinter.messagebox as messagebox
import tkinter.ttk as ttk
class GUI(ttk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.master.title("密码字典生成器")
self.grid()
self.create_widgets()
def create_widgets(self):
self.cue_label1 = ttk.Label(self, text="起始长度")
self.cue_label1.grid(row=0, column=0)
self.cue_label2 = ttk.Label(self, text="结束长度")
self.cue_label2.grid(row=0, column=1)
self.entry_var1 = tk.StringVar()
self.entry_var2 = tk.StringVar()
self.entry1 = ttk.Entry(self, textvariable=self.entry_var1, justify=tk.CENTER)
self.entry1.grid(row=1, column=0)
self.entry2 = ttk.Entry(self, textvariable=self.entry_var2, justify=tk.CENTER)
self.entry2.grid(row=1, column=1)
self.check_frame = ttk.Frame(self)
self.check_frame.grid(row=2, column=0, rowspan=2)
self.var_upper = tk.BooleanVar()
self.var_lower = tk.BooleanVar()
self.var_digit = tk.BooleanVar()
self.var_punct = tk.BooleanVar()
self.check_upper = ttk.Checkbutton(
self.check_frame, text="大写字母", variable=self.var_upper
)
self.check_upper.grid(row=0, column=0)
self.check_lower = ttk.Checkbutton(
self.check_frame, text="小写字母", variable=self.var_lower
)
self.check_lower.grid(row=0, column=1)
self.check_digit = ttk.Checkbutton(
self.check_frame, text="数字", variable=self.var_digit
)
self.check_digit.grid(row=0, column=2)
self.check_punct = ttk.Checkbutton(
self.check_frame, text="特殊字符", variable=self.var_punct
)
self.check_punct.grid(row=0, column=3)
self.export_frame = ttk.Frame(self)
self.export_frame.grid(row=2, column=1)
self.button_export = ttk.Button(
self.export_frame, text="导出", command=self.export_cmd
)
self.button_export.grid(row=0, column=0)
self.model_var = tk.BooleanVar()
self.model_var.set(True)
self.check_model = ttk.Checkbutton(
self.export_frame, text="追加模式", variable=self.model_var
)
self.check_model.grid(row=0, column=1)
self.c_label = ttk.Label(self, text="Free Software From Www.52PoJie.Cn")
self.c_label.grid(row=3, column=1)
def export_cmd(self):
try:
self.length_small = int(self.entry_var1.get())
self.length_big = int(self.entry_var2.get())
if self.length_small = self.length_big:
messagebox.showwarning("错误", "请按照提示输入")
return ""
except ValueError:
messagebox.showerror("错误", "请输入整数")
return ""
self.length = list(range(self.length_small, self.length_big + 1))
allowed_chars = ""
if self.var_upper.get():
allowed_chars += string.ascii_uppercase
if self.var_lower.get():
allowed_chars += string.ascii_lowercase
if self.var_digit.get():
allowed_chars += string.digits
if self.var_punct.get():
allowed_chars += string.punctuation
self.charset = list(allowed_chars)
if not self.charset:
messagebox.showwarning("错误", "请至少选择一个字符集")
return ""
file_name = filedialog.asksaveasfilename(
filetypes=[("文本文档", "*.txt"), ("所有文件", "*.*")]
)
self.result = gen(self.length, self.charset)
try:
self.export_file(self.result, file_name)
except Exception:
messagebox.showerror("错误", "导出失败")
return ""
messagebox.showinfo("成功", "导出成功")
def export_file(self, content, file_name):
if self.model_var.get():
with open(file_name, "a", encoding="utf-8") as f:
for item in content:
f.write("%s\n" % item)
else:
with open(file_name, "w", encoding="utf-8") as f:
for item in content:
f.write("%s\n" % item)
def main():
root = tk.Tk()
gui = GUI(master=root)
gui.master.mainloop()
# main()
GUI说明
此GUI仅提供最基础功能,在面对生成大字典时普遍会造成较长的卡顿,有条件还是自己配置GUI,异步,多进程等.