简体   繁体   English

密码没有创建到指定的长度?

[英]Password is not created to specified length?

I am creating a random password generator that takes in a user specified length but I have not been able to create the function in a way that it will make the password exactly that length. 我正在创建一个随机密码生成器,该生成器采用用户指定的长度,但是我无法以使密码完全符合该长度的方式创建该函数。 I have only been able to do it to multiples of 4 because of the 4 variables I have created. 由于创建了4个变量,所以我只能将其乘以4的倍数。 If i was to call the function with a different value like 10, the password would not be length 10. Any suggestions? 如果我要使用其他值(例如10)来调用该函数,则密码长度将不是10。有什么建议吗? Also the reason I am dividing by 4 is so that the for loop does not generate a password 4 times the leng. 另外,我将其除以4的原因是,for循环不会生成4倍长度的密码。

numbers = '1234567890'
letters = 'qwertyuiopasdfghjklzxcvbnm'
letters_caps = 'QWERTYUIOPLKJHGFDSAZXCVBNM'
symbols = '!@#$%^&*()_+=~`:"<>?|\;,."`'

def create_password(leng):
    password = ''
    lis = []
    for i in range(leng / 4):
        randnum = numbers[random.randrange(0, len(numbers))]
        lis.append(randnum)
        randletter = letters[random.randrange(0, len(letters))]
        lis.append(randletter)
        randletter_cap = letters_caps[random.randrange(0, len(letters_caps))]
        lis.append(randletter_cap)
        randsymbol = symbols[random.randrange(0, len(symbols))]
        lis.append(randsymbol)
    for items in lis:
        password += random.choice(lis)
    print password
create_password(12)

How about this: 这个怎么样:

numbers = '1234567890'
letters = 'qwertyuiopasdfghjklzxcvbnm'
letters_caps = 'QWERTYUIOPLKJHGFDSAZXCVBNM'
symbols = '!@#$%^&*()_+=~`:"<>?|\;,."`'

import random

raw_psw = numbers + letters + letters_caps + symbols
raw_psw = list(raw_psw)

length = 10
for _ in range(5):
    random.shuffle(raw_psw)
    print("".join(raw_psw[:length]))

cVY;U<,9Fx cVY; U <,9Fx

$dt_2wx^PJ $ dt_2wx ^ PJ

9oH|kU~2^g 9oH | kU〜2 ^ g

kJO@n`5H9Z kJO @ n`5H9Z

Y%oEXeOLv3 Y%oEXeOLv3

If you're just concerned about the length and are otherwise happy with your function, the simplest solution would be to round up to the next multiple of four, and then truncate the password before returning it, like: 如果您只是担心长度而对功能不满意,最简单的解决方案是将其四舍五入到下一个四倍,然后在返回密码之前截断密码,例如:

def create_password(leng):
    password = ''
    for i in range((leng + 3) // 4):
        # add 4 characters however you like
        # ...
    print password[:leng] # truncate to proper length

(As an aside, others have noted that it would be better to use the ''.join() construct rather than append in a loop, it is important to use a secure PRNG to generate passwords, and your code is probably more flexible if you return the password rather than printing it.) ''.join()说一句,其他人指出,最好使用''.join()构造而不是在循环中追加,使用安全的PRNG生成密码很重要,并且如果您return密码而不是打印密码。)

Perhaps the least intrusive change would be to loop exactly the number of times you specify, and call a different function depending on the modulo. 干扰最小的更改可能是准确地循环指定的次数,并根据模数调用不同的函数。

for i in range(leng):
    mod = i % 4
    if mod == 0:
        randitem = numbers[random.randrange(0, len(numbers))]
    elif mod == 1:
        randitem = letters[random.randrange(0, len(letters))]
    elif mod == 2:
        randitem = letters_caps[random.randrange(0, len(letters_caps))]
    else:
        randitem = symbols[random.randrange(0, len(symbols))]
    lis.append(randitem)

This obviously creates a slight skew towards the items towards the beginning of the loop; 显然,这会导致在循环开始时对项目略有倾斜; there is a 75% chance that there will be one more number than there are symbols from the other groups, 50% change for one letter symbol more, etc. 有75%的可能性将有一个比其他组中的符号多的数字,一个字母符号有50%的变化,等等。

Maybe a better approach would be to choose at random from all groups evenly and accept that true randomness means you will not always receive symbols from every group. 也许更好的方法是从所有组中随机选择并接受真正的随机性,这意味着您将不会总是收到每个组的符号。 This obviously increases the search space for an attacker, because the choice of valid passwords is less constrained. 显然,这增加了攻击者的搜索空间,因为有效密码的选择受到了较少的限制。

Just for pass time: 只是为了打发时间:

class PasswordGenerator(object):
    def __init__(self, alphabet_classes, r=None):
        from random import SystemRandom
        self.__alphabet_classes = alphabet_classes
        self.__random = r if r else SystemRandom()

    def generate(self, length):
        password = []

        n_classes = len(self.__alphabet_classes)

        idx = [i for i in range(n_classes)]
        self.__random.shuffle(idx)

        for i in range(length):
            password.append(self.__random.choice(self.__alphabet_classes[idx[i % n_classes]]))
        self.__random.shuffle(password)

        return ''.join(password)


if __name__ == '__main__':
    numbers = '1234567890'
    letters = 'qwertyuiopasdfghjklzxcvbnm'
    letters_caps = 'QWERTYUIOPLKJHGFDSAZXCVBNM'
    symbols = '!@#$%^&*()_+=~`:"<>?|\;,."`'
    pg = PasswordGenerator([numbers, letters, letters_caps, symbols])
    for _ in range(5):
        print(pg.generate(1))

So the main loop goes from 1 to n-1 , where n is the length given, in the loop we first decide which set of characters to use, then choose from that set by using random.choice . 因此,主循环从1到n-1 ,其中n是给定的长度,在循环中,我们首先确定要使用的字符集,然后使用random.choice从该字符集中选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM