【问题标题】:Python v3 ( Random password generator )Python v3(随机密码生成器)
【发布时间】:2023-06-02 20:29:01
【问题描述】:

我的问题是:如何生成每次生成长度从(8 到 12 个字符)不等的随机密码。

这是我的代码:

import string
import random

def randompassword():
    chars=string.ascii_uppercase + string.ascii_lowercase + string.digits
    size=8 
    return ''.join(random.choice(chars) for x in range(size,12))

print(randompassword())

【问题讨论】:

  • 由于 range(8, 12) 有 4 个元素,这不会只生成一个长度为 4 的密码吗?

标签: python python-3.x


【解决方案1】:

size = 8; range(size, 12) 总是返回数组[8,9,10,11],所以你总是得到一个长度为 4 的密码。 相反,请提前使用randint 确定此特定密码的大小:

import string
import random

def randompassword():
  chars = string.ascii_uppercase + string.ascii_lowercase + string.digits
  size = random.randint(8, 12)
  return ''.join(random.choice(chars) for x in range(size))

【讨论】:

  • 谢谢 :) 我错过了 randint 函数。
  • 如果不是很明显,这也适用于 Python 2。
【解决方案2】:

此问题存在细微差别,某些解决方案可能会导致password weakness 问题。考虑以下细微差别以及替代解决方案。

  • 一些答案​​使用string.printable,但这不是一个好主意,因为它包含空白字符。虽然它们对于密码来说并不是严格非法的,但您不能轻易看到它们,因此无法区分,例如,一个 tab 和几个 spaces(等等)。 下面我只使用小写字母和大写字母、数字和标点符号
  • 根据 element-position 从一组字符中随机选择不是随机的,因为每个包含的 character-class 的基数不是均匀分布的:26 小写字母; 26 大写字母; 10 位; 32 个标点符号。因此生成的密码可能包含比标点符号和数字更多的字母;标点符号多于数字; (等等)。因此,如果使用 random.choices()(与其他答案一样),还应该使用它的 weights=cum_weights= 选项,以消除上述偏差并平衡分布。
  • 也就是说,对于这个用例,我鼓励使用 Python 的 secrets 模块而不是它的 random 模块。来自他们的documentation on random

警告:不应使用此模块的伪随机生成器 出于安全目的。有关安全或加密用途,请参阅 secrets 模块。

这是一个使用 Python-3面向功能的解决方案。它仅使用secrets.choice()它并没有完全解决随机问题(其他细微差别仍然存在),但它确实改善了选择分布以减少偏差:

>>> import string, secrets

>>> char_classes = (string.ascii_lowercase,
                    string.ascii_uppercase,
                    string.digits,
                    string.punctuation)

>>> size = lambda: secrets.choice(range(8,13))                  # Chooses a password length.
>>> char = lambda: secrets.choice(secrets.choice(char_classes)) # Chooses one character, uniformly selected from each of the included character classes.
>>> pw   = lambda: ''.join([char() for _ in range(size())])     # Generates the variable-length password.

DEMO:使用从我们每个字符类中统一选择的字符生成 10 个可变长度密码字符串:

>>> for i in range(1,11):
>>>    p = pw()
>>>    print('%i) %i chars :: %s' % (i,len(p),p))
 1) 11 chars :: IwWNEAUmnJt
 2) 10 chars :: ;N/'tO6RTv
 3)  8 chars :: l=5.2CDh
 4) 10 chars :: V0=I+A`t2Q
 5) 12 chars :: PQm8:f,#56"9
 6) 10 chars :: KOdx9~%r;F
 7) 11 chars :: <?67U8}3>F{
 8) 11 chars :: G$5y~3fE7o*
 9) 10 chars :: 70,|=Rexwn
10)  8 chars :: &31P^@cU

最后,虽然我们在这里使用了secrets 模块,但可以使用numpynumpy.random 完成类似的操作。我希望这会有所帮助!

【讨论】:

    【解决方案3】:

    string.ascii_letters #考虑所有小写字母和大写字母。 string.digits #考虑 0 到 9 位数字。 string.punctuation #考虑符号等特殊字符。 random.choice #考虑从给定数据中随机选择。 range(random.randint(6, 12)) #考虑从给定数据中选择一个随机整数范围。 print(generator_pw()) #打印随机生成的密码。

    import random, string
    
    def generator_pw():
        pwd = string.ascii_letters + string.digits + string.punctuation
        return "".join(random.choice(pwd) for x in range(random.randint(6, 12)))
    
    print(generator_pw())
    

    【讨论】:

      【解决方案4】:

      由于size = 8range(size,12),我相信它只打印了 4 个字符。这转换为 range(8, 12) = 4 个字符。您可以增加第二个数字以分配更大的范围以打印随机字符,如下所示

      import string
      import random
      
      def randompassword():
          chars=string.ascii_uppercase + string.ascii_lowercase + string.digits
          size= 8
          return ''.join(random.choice(chars) for x in range(size,20))
      
      print(randompassword())
      

      还请务必查看 python 的随机文档here

      【讨论】:

        【解决方案5】:

        编辑:如下所述,string.printable 字符串包含在用于密码时可能导致问题的字符。与其依赖这个内置集,不如定义一组自定义的可用字符。不要忘记将字符作为空格,它们是 LHF 以提高密码强度。请务必处理标题/尾部空格,因为 UI 可能会剥夺用户的输入,从而阻止他们输入有效密码。

        import random
        import string
        
        def randompassword():
            return ''.join([random.choice(string.printable) for _ in range(random.randint(8, 12))])
        
        罢工>

        【讨论】:

        • string.printable 包含 \t \n 和其他一些不适合密码的内容。
        • @IstvanSzekeres 这是一个有效的观点,我已经相应地编辑了我的答案。感谢您指出这一点。
        【解决方案6】:

        range(size,12) 仅返回介于size(您已硬编码为 8)和 12 之间的数字,因此您的密码长度仅为 4 个字符。让... for x in range(size).

        【讨论】: