Always use urandom in all functions. Remove --urandom option.

master
voussoir 2022-01-09 17:05:03 -08:00
parent d34103917f
commit 8b4202fe87
No known key found for this signature in database
GPG Key ID: 5F7554F8C26DACCB
1 changed files with 29 additions and 25 deletions

View File

@ -2,7 +2,11 @@
passwordy passwordy
========= =========
This module provides functions for generating random strings. This module provides functions for generating random strings. All functions use
cryptographically strong randomness if the operating system supports it, and
non-cs randomness if it does not.
If os.urandom(1) gives you a byte, your system has cs randomness.
Command line usage: Command line usage:
@ -19,13 +23,6 @@ length:
--separator <string>: --separator <string>:
When using sentence mode, the words will be joined with this string. When using sentence mode, the words will be joined with this string.
# urandom mode:
--urandom:
If this argument is passed, os.urandom is called for cryptographically
strong randomness and the password is shown as hex.
Only --upper and --lower can be used in urandom mode (though the hex is
lowercase by default).
# Normal mode: # Normal mode:
--letters: --letters:
Include ASCII letters in the password. Include ASCII letters in the password.
@ -59,12 +56,19 @@ import sys
from voussoirkit import betterhelp from voussoirkit import betterhelp
from voussoirkit import pipeable from voussoirkit import pipeable
try:
os.urandom(1)
RNG = random.SystemRandom()
except NotImplementedError:
RNG = random
def make_password( def make_password(
length, length,
letters=False, *,
binary=False,
digits=False, digits=False,
hex=False, hex=False,
binary=False, letters=False,
punctuation=False, punctuation=False,
): ):
alphabet = set() alphabet = set()
@ -82,7 +86,7 @@ def make_password(
if not alphabet: if not alphabet:
raise ValueError('No alphabet options chosen.') raise ValueError('No alphabet options chosen.')
return ''.join(random.choices(tuple(alphabet), k=length)) return ''.join(RNG.choices(tuple(alphabet), k=length))
def make_sentence(length, separator=' '): def make_sentence(length, separator=' '):
''' '''
@ -90,18 +94,21 @@ def make_sentence(length, separator=' '):
dictionary.common. dictionary.common.
''' '''
import dictionary.common as common import dictionary.common as common
words = random.choices(common.words, k=length) words = RNG.choices(common.words, k=length)
words = [w.replace(' ', separator) for w in words] words = [w.replace(' ', separator) for w in words]
result = separator.join(words) result = separator.join(words)
return result return result
def random_hex(length): def random_digits(length):
randbytes = os.urandom(math.ceil(length / 2)) '''
token = ''.join('{:02x}'.format(x) for x in randbytes) Shortcut function for when you don't want to type the make_password call.
token = token[:length] '''
return token return ''.join(RNG.choices(string.digits, k=length))
def urandom_hex(length): def random_hex(length):
'''
Shortcut function for when you don't want to type the make_password call.
'''
randbytes = os.urandom(math.ceil(length / 2)) randbytes = os.urandom(math.ceil(length / 2))
token = ''.join('{:02x}'.format(x) for x in randbytes) token = ''.join('{:02x}'.format(x) for x in randbytes)
token = token[:length] token = token[:length]
@ -110,19 +117,17 @@ def urandom_hex(length):
def passwordy_argparse(args): def passwordy_argparse(args):
if args.sentence: if args.sentence:
password = make_sentence(args.length, args.separator) password = make_sentence(args.length, args.separator)
elif args.urandom:
password = urandom_hex(args.length)
else: else:
if not any([args.letters, args.digits, args.hex, args.binary, args.punctuation]): if not any([args.letters, args.digits, args.hex, args.binary, args.punctuation]):
letters = True letters = True
else: else:
letters = args.letters letters = args.letters
password = make_password( password = make_password(
length=args.length, args.length,
letters=letters, binary=args.binary,
digits=args.digits, digits=args.digits,
hex=args.hex, hex=args.hex,
binary=args.binary, letters=letters,
punctuation=args.punctuation, punctuation=args.punctuation,
) )
if args.lower: if args.lower:
@ -136,9 +141,8 @@ def main(argv):
parser = argparse.ArgumentParser(description=__doc__) parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('length', type=int) parser.add_argument('length', type=int)
parser.add_argument('--urandom', action='store_true')
parser.add_argument('--sentence', action='store_true') parser.add_argument('--sentence', action='store_true')
parser.add_argument('--separator', nargs='?', default=' ') parser.add_argument('--separator', default=' ')
parser.add_argument('--letters', action='store_true') parser.add_argument('--letters', action='store_true')
parser.add_argument('--digits', action='store_true') parser.add_argument('--digits', action='store_true')
parser.add_argument('--hex', action='store_true') parser.add_argument('--hex', action='store_true')