1,66 → 1,124 |
#!/usr/bin/env python |
|
""" |
Simplistic Password Generator. |
""" |
|
# This file is released under the CC0 license (CC equivalent of Public Domain). |
# |
# License details: |
# http://creativecommons.org/publicdomain/zero/1.0/legalcode |
|
import random |
import string |
import locale |
import sys |
|
DEFAULT_RESULTS = 20 |
DEFAULT_LENGTH = 8 |
#Letters and digits are repeated to favour them |
FAVOURED_SET = string.lowercase + string.digits #string.letters |
STDSET = string.uppercase + string.punctuation |
DEFAULT_CSET = FAVOURED_SET * 8 + STDSET |
|
REJECTS_SET = [ 'l', '1', 'I', '0', 'O' ] # FIXME: What else? |
|
def pwgen(length=DEFAULT_LENGTH, possible=DEFAULT_CSET, reject_ambiguous=False): |
pw = '' |
rejects = [] |
if reject_ambiguous: |
rejects = REJECTS_SET |
for i in range(length): |
pick = random.choice(possible) |
while pick in rejects: |
pick = random.choice(possible) |
pw += pick |
return pw |
|
def main(argv): |
rounds = DEFAULT_RESULTS |
length = DEFAULT_LENGTH |
cset = DEFAULT_CSET |
reject_ambiguous = False |
|
# No need to use getopt or anything like it |
positional = [] |
for arg in argv: |
if arg in ( '-B', '--ambiguous' ): |
reject_ambiguous = True |
else: |
positional.append(arg) |
try: |
if len(positional) > 0: |
length = int(positional[0]) |
if len(positional) > 1: |
rounds = int(positional[1]) |
except ValueError: |
sys.stderr.write('Usage: pwgen [-B] [length] [num pw]\n'); |
sys.exit(2); |
|
for i in range(rounds): |
print pwgen(length=length, reject_ambiguous=reject_ambiguous) |
|
if __name__ == '__main__': |
locale.setlocale(locale.LC_ALL, 'C') |
main(sys.argv[1:]) |
|
#!/usr/bin/env python |
|
""" |
Simplistic Password Generator. |
""" |
|
# This file is released under the CC0 license (CC equivalent of Public Domain). |
# |
# License details: |
# http://creativecommons.org/publicdomain/zero/1.0/legalcode |
|
import random |
import string |
import locale |
import sys |
|
try: |
import checkpw |
DO_CHECK=True |
except ImportError: |
DO_CHECK=False |
|
DEFAULT_RESULTS = 20 |
DEFAULT_LENGTH = 8 |
#Letters and digits are repeated to favour them |
FAVOURED_SET = string.lowercase + string.digits #string.letters |
STDSET = string.uppercase + string.punctuation |
DEFAULT_CSET = FAVOURED_SET * 8 + STDSET |
|
REJECTS_SET = [ 'l', '1', 'I', '0', 'O' ] # FIXME: What else? |
DEFAULT_FORCE = '*' # Symbolic |
|
def pwgen(length=DEFAULT_LENGTH, possible=DEFAULT_CSET, |
reject_ambiguous=False, force=DEFAULT_FORCE): |
''' |
pwgen(int, str, bool, [ str, str, ...]) -> str |
|
Generate a password. |
length - Password length |
possible - List of characters from where to pick |
reject_ambiguous - Reject characters that can be hard to tell from each other (e.g. 1 vs l vs I) |
force - List of forcible sets. Force at least one character of each set. |
''' |
pw = '' |
rejects = [] |
LENGTH = length |
if reject_ambiguous: |
rejects = REJECTS_SET |
if force == DEFAULT_FORCE: |
force = [ string.lowercase, string.uppercase, string.digits ] |
if type(force) != list: |
raise ValueError('force must be a list of strings') |
def pick_one(cset): |
''' |
Return a random character from cset |
''' |
c = random.choice(cset) |
while c in rejects: |
c = random.choice(cset) |
return c |
# Forcible includes |
for cset in force: |
pw += pick_one(cset) |
length -= 1 |
for i in range(length): |
pick = random.choice(possible) |
while pick in rejects: |
pick = random.choice(possible) |
pw += pick |
# Re-mix order (randomize forced-characters' position) |
if len(pw) > LENGTH: |
pw = pw[0:LENGTH] |
l = list(pw) |
random.shuffle(l) |
pw = ''.join(l) |
return pw |
|
def main(argv): |
rounds = DEFAULT_RESULTS |
length = DEFAULT_LENGTH |
cset = DEFAULT_CSET |
reject_ambiguous = False |
secure = False # When True, reject mediocre passwords and below |
|
# No need to use getopt or anything like it |
positional = [] |
for arg in argv: |
if arg in ( '-B', '--ambiguous' ): |
reject_ambiguous = True |
elif arg in ( '-s', '--secure' ): |
if not DO_CHECK: |
raise EnvironmentError('Can\'t generate secure-only password without checkpw.py') |
secure = True |
else: |
positional.append(arg) |
try: |
if len(positional) > 0: |
length = int(positional[0]) |
if len(positional) > 1: |
rounds = int(positional[1]) |
except ValueError: |
sys.stderr.write('Usage: pwgen [-B] [length] [num pw]\n'); |
sys.exit(2); |
|
def newpw(): |
return pwgen(length=length, reject_ambiguous=reject_ambiguous) |
|
for i in range(rounds): |
pw = newpw() |
if DO_CHECK: |
( score, verdict, _ ) = checkpw.check(pw) |
while score < checkpw.STRONG_THRESHOLD: |
pw = newpw() |
( score, verdict, _ ) = checkpw.check(pw) |
print '%s\t%d\t%s' % ( pw, score, verdict) |
#print _ |
else: |
print pw |
|
if __name__ == '__main__': |
locale.setlocale(locale.LC_ALL, 'C') |
main(sys.argv[1:]) |
|
# vim:set ts=4 et ai: # |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |