吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3276|回复: 45
收起左侧

[Python 原创] 用python写了一个随机密码生成器,分享一下

  [复制链接]
bing52 发表于 2023-12-2 18:06
本帖最后由 bing52 于 2023-12-2 18:09 编辑

编程语言: python3.11
图形模块: PySimpleGUI
实现思路:
1. 密码组成部分:大写字母,小写字母,数字,特殊字符
2. 根据用户选择的组成部分和密码长度
     2.1: 计算组成部分个数n, 将密码长度随机分成n份生成列表m
     2.2: 根据遍历并随机获取每个组成部分的数据,每个组成部分的长度m
     2.3: 打乱顺序,组装成字符串输出
成品:

效果演示

效果演示

关键代码:
[Python] 纯文本查看 复制代码
def getRandom(leng: int, typnum: int):
    num_list = []
    # 如果密码长度和密码复杂度一致,就默认设置为1
    if leng == typnum:
        return [1 for _ in range(typnum)]

    for i in range(typnum, 0, -1):
        num_list.append(random.randint(1, leng - sum(num_list) - i))
    num_list[num_list.index(min(num_list))] += leng - sum(num_list)
    num_list.sort(reverse=True)
    return num_list


def randmima(key: list[str],
             leng: int,
             special: Optional[str] = '~!@#$%^&*()-_=+?><.,'):
    # 字典项
    atomDict = {
        'lowers': string.ascii_lowercase,
        'uppers': string.ascii_uppercase,
        'numbers': string.digits,
        'sym': special if special else string.punctuation
    }

    # 获取每个原子项分的长度数组
    if len(key) > leng:
        raise KeyError("密码长度不能小于复杂度个数")

    numList = getRandom(leng, len(key))
    seclist = []
    for index, value in enumerate(numList):
        seclist += random.choices(atomDict[key[index]], k=value)

    # 重新排序
    random.shuffle(seclist)

    return "".join(seclist)


def batchPwd(optionDict: dict) -> str:
    atomList = ['lowers', 'uppers', 'numbers', 'sym']
    secList = []
    atom = [
        key for key, value in optionDict.items() if key in atomList and value
    ]

    # 判断原子数据是否为空
    if not atom:
        return "至少选择一项"

    random.shuffle(atom)

    for _ in range(int(optionDict['pwdCount'])):
        secList.append(
            randmima(atom,
                     int(optionDict['pwdlength']),
                     special=optionDict['spclistr']))

    return "\n".join(secList)


def main():
    # 图形界面
    pdict = {
        'uppers': True,
        'lowers': True,
        'numbers': True,
        'sym': True,
        'pwdlength': 12,
        'pwdCount': 5,
        'spclistr': None
    }

    sg.theme("Dark Brown")
    optional = {'font': "MicrosoftYaHei 14", "margins": (10, 10)}
    config_option_spcil1 = [
        sg.Checkbox("大写字母", default=True, key="uppers", enable_events=True),
        sg.Checkbox("小写字母", default=True, key="lowers", enable_events=True),
        sg.Checkbox("数字", default=True, key="numbers", enable_events=True)
    ]

    config_spcil2_option = [
        sg.Checkbox('', default=True, key="sym", enable_events=True),
        sg.Input('.,$#@!^&*-_=+:;?',
                 size=(25, 1),
                 key="spclistr",
                 disabled=False,
                 enable_events=True)
    ]
    config_option = [
        sg.Text("密码组成: "),
        sg.Column([config_option_spcil1, config_spcil2_option])
    ]
    config_resgen_btn = [sg.Button("重新生成", key='-regeneration-')]
    btn_column = [sg.Column([config_resgen_btn], justification="right")]
    pwd_length_option = [
        sg.Text("密码长度: "),
        sg.Slider(range=(4, 50),
                  default_value=pdict['pwdlength'],
                  orientation='h',
                  enable_events=True,
                  disable_number_display=True,
                  size=(28, 15),
                  key='pwdlength'),
        sg.Text(pdict['pwdlength'], key='-PWDLEN-')
    ]
    config_count = [
        sg.Text("生成个数: "),
        sg.Slider(range=(1, 100),
                  default_value=pdict['pwdCount'],
                  orientation='h',
                  enable_events=True,
                  disable_number_display=True,
                  size=(28, 15),
                  key='pwdCount'),
        sg.Text(pdict['pwdCount'], key='-count-')
    ]
    result_option = [
        sg.Multiline(default_text=batchPwd(pdict),
                     autoscroll=True,
                     horizontal_scroll=True,
                     disabled=True,
                     size=(50, 15),
                     key="-pwdResult-")
    ]
    layout = [[
        sg.Frame("参数设置",
                 [config_option, pwd_length_option, config_count, btn_column],
                 size=(450, 200))
    ], [sg.Frame("执行结果", [result_option], size=(450, 300))]]
    window = sg.Window("随机密码生成器", layout=layout, **optional)
    while True:
        event, values = window.read()  # type: ignore
        if event == sg.WIN_CLOSED:
            break
        if event == 'pwdCount':
            window['-count-'].update(value=str(int(values['pwdCount'])))
        if event == 'pwdlength':
            window['-PWDLEN-'].update(value=str(int(values['pwdlength'])))
        if event == 'sym':
            window['spclistr'].update(disabled=not values['sym'])
        if event in [
                'sym', 'numbers', 'lowers', 'uppers', 'pwdlength', 'pwdCount',
                'spclistr', '-regeneration-'
        ]:
            window['-pwdResult-'].update(value=batchPwd(values))

    window.close()

if __name__ == "__main__":
    main()



关键代码都在这里了,我就不搞文件了。各位如果有什么好的想法和建议可以留言

免费评分

参与人数 5吾爱币 +10 热心值 +4 收起 理由
David13738 + 1 + 1 热心回复!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
ma4907758 + 1 谢谢@Thanks!
mzq2mmd + 1 + 1 我很赞同!
hrh123 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

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

 楼主| bing52 发表于 2023-12-3 20:48
本帖最后由 bing52 于 2023-12-3 20:49 编辑

根据各位提的意见,我又修改了一版添加了自动复制的功能, 不过用listbox有个bug,就是一些特殊字符的密码显示的时候会用{}包裹,搞了半天没有搞定,不过不影响复制和粘贴, 有大佬搞定的可以告诉我一下
bug截图:
Snipaste_2023-12-03_20-30-28.png

修改后的代码:
[Python] 纯文本查看 复制代码
import random
import string
from typing import Optional
import PySimpleGUI as sg
import pyperclip as pc


def getRandom(leng: int, typnum: int):
    num_list = []
    # 如果密码长度和密码复杂度一致,就默认设置为1
    if leng == typnum:
        return [1 for _ in range(typnum)]

    for i in range(typnum, 0, -1):
        num_list.append(random.randint(1, leng - sum(num_list) - i))
    num_list[num_list.index(min(num_list))] += leng - sum(num_list)
    num_list.sort(reverse=True)
    return num_list


def randmima(key: list[str],
             leng: int,
             special: Optional[str] = '~!@#$%^&*()-_=+?><.,'):
    # 字典项
    atomDict = {
        'lowers': string.ascii_lowercase,
        'uppers': string.ascii_uppercase,
        'numbers': string.digits,
        'sym': special if special else string.punctuation
    }

    # 获取每个原子项分的长度数组
    if len(key) > leng:
        raise KeyError("密码长度不能小于复杂度个数")

    numList = getRandom(leng, len(key))
    seclist = []
    for index, value in enumerate(numList):
        seclist += random.choices(atomDict[key[index]], k=value)

    # 重新排序
    random.shuffle(seclist)

    return "".join(seclist)


def batchPwd(optionDict: dict) -> list:
    atomList = ['lowers', 'uppers', 'numbers', 'sym']
    secList = []
    atom = [
        key for key, value in optionDict.items() if key in atomList and value
    ]

    # 判断原子数据是否为空
    if not atom:
        return ["至少选择一项"]

    random.shuffle(atom)

    for index in range(int(optionDict['pwdCount'])):
        secList.append(
            [f'{index + 1}.', randmima(atom, int(optionDict['pwdlength']), special=optionDict['spclistr'])])
    # return "\n".join(secList)
    return secList


def main():
    # 图形界面
    pdict = {
        'uppers': True,
        'lowers': True,
        'numbers': True,
        'sym': True,
        'pwdlength': 12,
        'pwdCount': 5,
        'spclistr': None
    }
    pwds = batchPwd(pdict)
    sg.theme("Dark Brown")
    optional = {'font': "MicrosoftYaHei 14", "margins": (10, 10)}
    config_option_spcil1 = [
        sg.Checkbox("大写字母", default=True, key="uppers", enable_events=True),
        sg.Checkbox("小写字母", default=True, key="lowers", enable_events=True),
        sg.Checkbox("数字", default=True, key="numbers", enable_events=True)
    ]

    config_spcil2_option = [
        sg.Checkbox('', default=True, key="sym", enable_events=True),
        sg.Input('.,$#@!^&*-_=+:;?',
                 size=(25, 1),
                 key="spclistr",
                 disabled=False,
                 enable_events=True)
    ]
    config_option = [
        sg.Text("密码组成: "),
        sg.Column([config_option_spcil1, config_spcil2_option])
    ]
    config_resgen_btn = [sg.Button("重新生成", key='-regeneration-')]
    btn_column = [sg.Column([config_resgen_btn], justification="right")]
    pwd_length_option = [
        sg.Text("密码长度: "),
        sg.Slider(range=(4, 50),
                  default_value=pdict['pwdlength'],
                  orientation='h',
                  enable_events=True,
                  disable_number_display=True,
                  size=(28, 15),
                  key='pwdlength'),
        sg.Text(pdict['pwdlength'], key='-PWDLEN-')
    ]
    config_count = [
        sg.Text("生成个数: "),
        sg.Slider(range=(1, 100),
                  default_value=pdict['pwdCount'],
                  orientation='h',
                  enable_events=True,
                  disable_number_display=True,
                  size=(28, 15),
                  key='pwdCount'),
        sg.Text(pdict['pwdCount'], key='-count-')
    ]

    result_option_list = [sg.Listbox(
        values=pwds, enable_events=True, key='-listpwd-', size=(50, 15))]
    propmsg = [sg.Column(
        [[sg.Text(text="点击单条密码,可自动复制", text_color='white', k='-PropMsg-')]], justification='center')]
    copyAll = [
        sg.Column([[sg.Button("复制所有密码", k='-COPYAll-', enable_events=True)]], justification='center')]
    layout = [[
        sg.Frame("参数设置",
                 [config_option, pwd_length_option, config_count, btn_column],
                 size=(450, 200))
    ],
        [sg.Frame("执行结果", [propmsg, result_option_list, copyAll], size=(450, 415))]]
    window = sg.Window("随机密码生成器", layout=layout, **optional)

    while True:
        event, values = window.read()  # type: ignore
        if event == sg.WIN_CLOSED:
            break
        if event == 'pwdCount':
            window['-count-'].update(value=str(int(values['pwdCount'])))
        if event == 'pwdlength':
            window['-PWDLEN-'].update(value=str(int(values['pwdlength'])))
        if event == 'sym':
            window['spclistr'].update(disabled=not values['sym'])
        if event in [
                'sym', 'numbers', 'lowers', 'uppers', 'pwdlength', 'pwdCount',
                'spclistr', '-regeneration-'
        ]:
            pwds = batchPwd(values)
            window['-listpwd-'].update(values=pwds)

        if event == '-listpwd-':
            sec_str = values['-listpwd-'][0][1]
            window['-PropMsg-'].update(value=f"密码: {sec_str} 已经复制到剪切板")
            pc.copy(sec_str)
        if event == '-COPYAll-':
            all_seclist = "\n".join([i[1] for i in pwds])
            pc.copy(all_seclist)
            window['-PropMsg-'].update(value=f"所有密码已经复制到剪切板")

    window.close()


if __name__ == "__main__":
    main()


本来我是要用pyinstaller 打包的,看到有人已经打包了我就没有上传,如果有需要打包exe可执行文件,请安装pyinstaller模块,
打包命令: pyinstaller -w -F xxxx.py
 楼主| bing52 发表于 2023-12-3 14:59
Listentomusic 发表于 2023-12-3 14:04
给楼主提个建议,如果可以点击生成的密码自动复制就好了

嗯,我研究研究
q197843 发表于 2023-12-3 02:21
InnocenceYv 发表于 2023-12-3 02:32
谢谢大佬,python 爱好者很好的示例
wyh138 发表于 2023-12-3 05:25
感谢分享&#128522;
ysf216 发表于 2023-12-3 07:16
谢谢分享
52soft 发表于 2023-12-3 07:35
提示:NameError: name 'Optional' is not defined  错误
jinqiaoa1a 发表于 2023-12-3 08:34
楼主辛苦,感谢提供
Manray 发表于 2023-12-3 09:35
不错不错,加一个简单界面,然后生成之后自动复制到剪贴板,并让输入网址和用户名等相关信息并保存,一个密码管理软件就形成了。
jyjjf 发表于 2023-12-3 10:18
随机关键在于随机函数上面,是不是真正随机
 楼主| bing52 发表于 2023-12-3 10:47
52soft 发表于 2023-12-3 07:35
提示:NameError: name 'Optional' is not defined  错误

发个截图把,你这个看不出来啥问题
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-24 16:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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