forked from lunar-debian/diceware-wordlists-fr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rolldice
executable file
·85 lines (55 loc) · 2.25 KB
/
rolldice
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env python3
import argparse
import math
import random
import re
import sys
MIN_ENTROPY = 44
def choose(words, nb):
rng = random.SystemRandom()
return [rng.choice(words) for i in range(nb)]
class Wordlist():
def __init__(self, words):
self.words = list(words)
self._len = len(self.words)
self.entropy_per_word = math.log(self._len, 2)
def __len__(self):
return self._len
def __getitem__(self, key):
return self.words[key]
def wordlist_from_file(wordfile):
is_diceware = bool(re.fullmatch('[0-9-]+\s[\w \'-]+', wordfile.readline().strip()))
wordfile.seek(0)
if is_diceware:
return Wordlist(word.strip().split(maxsplit=1)[1] for word in wordfile)
return Wordlist(word.strip() for word in wordfile)
def print_passphrase(words, entropy, sep=' ', verbose=False):
passphrase = sep.join(words)
# entropy could be less than expected if it's really short (1-2 chars
# words). Calculate real entropy, assuming [a-z] only words.
entropy = min(len(passphrase) * math.log(26, 2), entropy)
if entropy < MIN_ENTROPY:
print('Warning: the passphrase entropy of {:2.1f} bits seems very low.'.format(entropy),
file=sys.stderr)
if verbose:
print('Passphrase entropy: {:2.1f}'.format(entropy), file=sys.stderr)
print(passphrase)
def rolldice(wordfile, entropy=None, nb_words=None):
wordlist = wordlist_from_file(wordfile)
if nb_words is None:
nb_words = math.ceil(entropy / wordlist.entropy_per_word)
entropy = nb_words * wordlist.entropy_per_word
return choose(wordlist, nb_words), entropy
def main():
parser = argparse.ArgumentParser()
parser.add_argument('wordfile', type=argparse.FileType('r'))
group = parser.add_mutually_exclusive_group()
group.add_argument('-e', '--entropy', type=int, default=56)
group.add_argument('nb_words', type=int, nargs='?', default=None)
parser.add_argument('-s', '--separator', default=' ')
parser.add_argument('-v', '--verbose', action="store_true")
args = parser.parse_args()
words, entropy = rolldice(args.wordfile, args.entropy, args.nb_words)
print_passphrase(words, entropy, args.separator, args.verbose)
if __name__ == '__main__':
main()