forked from mk-fg/fgtk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
passgen
executable file
·51 lines (42 loc) · 2 KB
/
passgen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/env python3
import os, sys, math, random, subprocess as sp
def main(args=None):
import argparse
parser = argparse.ArgumentParser(
description='Generate random passphrase'
' using Diceware method and aspell "en" dictionary.')
parser.add_argument('-w', '--words', metavar='n', type=int, default=5,
help='Passphrase word count (default: %(default)s).')
parser.add_argument('-f', '--char-count-min', metavar='n', type=int, default=20,
help='Min passphrase character count (default: %(default)s).')
parser.add_argument('-t', '--char-count-max', metavar='n', type=int, default=60,
help='Max passphrase character count (default: %(default)s).')
parser.add_argument('-i', '--id', metavar='string',
help='Add some ID string (with randomized separator) to one of the words.')
parser.add_argument('-e', '--entropy-estimate', action='store_true',
help='Print rough entropy estimate of the'
' resulting passphrase (not counting the --id, if any).')
opts = parser.parse_args()
aspell = sp.run(['aspell', '-d', 'en', 'dump', 'master'], check=True, stdout=sp.PIPE)
aspell_words = list(set(aspell.stdout.decode().splitlines()))
aspell_words_ent = math.log(len(aspell_words), 2)
def get_word():
word = random.choice(aspell_words)
if word.endswith("'s"): word = word[:-2]
return word
words = list(get_word() for n in range(opts.words))
tries, a, b = 999, opts.char_count_min, opts.char_count_max
for n in range(tries):
words_len = sum(map(len, words))
if a <= words_len <= b: break
words[random.choice(range(len(words)))] = get_word()
else: parser.error(f'Failed to pick password of {a}-{b} chars within {tries} attempts')
if opts.id:
id_sep = random.choice('#@$%&^*!<>/?\|')
n = random.choice(range(len(words)))
words[n] = ''.join( [opts.id, id_sep, words[n]]
if random.random() > 0.5 else [words[n], id_sep, opts.id] )
print(' '.join(words))
if opts.entropy_estimate:
print('Entropy estimate: {:,.1f}b'.format(aspell_words_ent * len(words)))
if __name__ == '__main__': sys.exit(main())