forked from vinces1979/pwgen
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
If no_ambiguous is set, the ambiguous characters are now replaced one by one instead of throwing away the password and trying to generate a new one. This was a problem when generating long, non-ambiguous passwords. In addition, when symbols, numerals or capital letters are enforced, these characters will no longer be inserted at random positions in the password. Instead, they will only replace lowercase letters, if available. Otherwise, it was possible to e.g. overwrite the single numeral with a symbol if numerals and symbols are set and only one numeral but no symbols were present in the password (closes vinces1979#13).
- Loading branch information
Showing
1 changed file
with
33 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,6 @@ | |
2015 - Luar was here <[email protected]> | ||
""" | ||
|
||
import string | ||
import re | ||
|
||
|
@@ -23,20 +22,35 @@ | |
Digits = string.digits | ||
Symbols = string.punctuation | ||
|
||
HasLowercase = re.compile("[a-z]") | ||
HasCaps = re.compile("[A-Z]") | ||
HasNumerals = re.compile("[0-9]") | ||
HasSymbols = re.compile(r"[%s]" % re.escape(Symbols)) | ||
HasAmbiguous = re.compile("[B8G6I1l|0OQDS5Z2]") | ||
|
||
|
||
def replaceRandomChar(letter, word, pos=None): | ||
if not pos: | ||
"""Replace a character in the password with another. | ||
@param letter: The character to insert into the password | ||
@param word: The password to insert the letter into | ||
@param pos: The position the letter shall be inserted at (may be a | ||
position or a list of positions to choose from randomly) | ||
""" | ||
if isinstance(pos, list) and len(pos) > 0: | ||
pos = choice(pos) | ||
elif pos is not None: | ||
pos = randint(0, len(word)-1) | ||
word = list(word) | ||
word[pos] = letter | ||
return "".join(word) | ||
|
||
|
||
def findAllChars(word, pattern): | ||
"""Return a list of positions in the string where the pattern matches.""" | ||
return [m.start() for m in re.finditer(pattern, word)] | ||
|
||
|
||
def pwgen(pw_length=20, num_pw=1, no_numerals=False, no_capitalize=False, | ||
capitalize=False, numerals=False, no_symbols=True, symbols=False, | ||
allowed_symbols=None, no_ambiguous=False): | ||
|
@@ -76,13 +90,25 @@ def pwgen(pw_length=20, num_pw=1, no_numerals=False, no_capitalize=False, | |
while len(passwds) < int(num_pw): | ||
passwd = "".join(choice(letters) for x in range(pw_length)) | ||
if capitalize and not HasCaps.search(passwd): | ||
passwd = replaceRandomChar(choice(UpperCase), passwd) | ||
passwd = replaceRandomChar( | ||
choice(UpperCase), passwd, | ||
pos=findAllChars(passwd, HasLowercase) | ||
) | ||
if numerals and not HasNumerals.search(passwd): | ||
passwd = replaceRandomChar(choice(Digits), passwd) | ||
passwd = replaceRandomChar( | ||
choice(Digits), passwd, | ||
pos=findAllChars(passwd, HasLowercase) | ||
) | ||
if symbols and not HasSymbols.search(passwd): | ||
passwd = replaceRandomChar(choice(Symbols), passwd) | ||
if no_ambiguous and HasAmbiguous.search(passwd): | ||
continue | ||
passwd = replaceRandomChar( | ||
choice(Symbols), passwd, | ||
pos=findAllChars(passwd, HasLowercase) | ||
) | ||
while no_ambiguous and HasAmbiguous.search(passwd): | ||
passwd = replaceRandomChar( | ||
choice(letters), passwd, | ||
pos=findAllChars(passwd, HasAmbiguous) | ||
) | ||
passwds.append(passwd) | ||
|
||
if len(passwds) == 1: | ||
|