From c30ef0e4980c7773cbdb1c33eaf8fe14c8ffbe51 Mon Sep 17 00:00:00 2001 From: HacKan Date: Thu, 19 Jul 2018 20:31:35 -0300 Subject: [PATCH] Improve password generation Passwords were generated by randomly choosing items in a single group formed by the required characters, digits and symbols. The problem with that way of choosing items is that it doesn't consider the types of the items, thus getting more chances of choosing a letter than a number, given that the letters group is bigger than the numbers group. Now, I create a list with each required type of element (lower case chars, upper case chars, digits and symbols) and randomly pick one. Then I pick an item of that group. This way, each type of element has the same probability of being picked. --- passphrase/passphrase.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/passphrase/passphrase.py b/passphrase/passphrase.py index 1673beb..a0ece8f 100644 --- a/passphrase/passphrase.py +++ b/passphrase/passphrase.py @@ -210,7 +210,7 @@ def _read_words_from_diceware(inputfile: str) -> list: word.split()[1] for word in open(inputfile, mode='rt') ] - def _get_password_characters(self) -> str: + def _get_password_characters(self, cathegorized=False) -> str: from string import ( digits, ascii_lowercase, @@ -218,18 +218,18 @@ def _get_password_characters(self) -> str: punctuation ) - characters = '' + group = [] if self.password_use_lowercase: - characters += ascii_lowercase + group.append(ascii_lowercase) if self.password_use_uppercase: - characters += ascii_uppercase + group.append(ascii_uppercase) if self.password_use_digits: - characters += digits + group.append(digits) if self.password_use_punctuation: - characters += punctuation + group.append(punctuation) - return characters + return group if cathegorized else ''.join(group) def __init__( self, @@ -472,16 +472,18 @@ def generate_password(self) -> list: """Generates a list of random characters.""" password = [] - characters = self._get_password_characters() + characterset = self._get_password_characters(cathegorized=True) if ( self.passwordlen is None - or not characters + or not characterset ): raise ValueError("Can't generate password: character set is " "empty or passwordlen isn't set") for _ in range(0, self.passwordlen): - password.append(randchoice(characters)) + # The first choice is done to choose the set + # The second chooses an item in that set + password.append(randchoice(randchoice(characterset))) self.last_result = password return password