Skip to content

Instantly share code, notes, and snippets.

@markasoftware
Created January 19, 2018 04:20
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save markasoftware/1c5b52c0537a5a055ac8e61a85f9573e to your computer and use it in GitHub Desktop.
Save markasoftware/1c5b52c0537a5a055ac8e61a85f9573e to your computer and use it in GitHub Desktop.
Mnemonic password generator
#!/bin/bash
# help text
[[ $1 == *-h* || -z $1 ]] && echo 'Usage: mnemonic.sh word_count [min_length max_length]' && exit
# Where is the wordlist?
[[ -e /usr/dict/words ]] && dict_path='/usr/dict/words' || dict_path='/usr/share/dict/words'
# Remove words with apostrophes, capitalization, or outside the correct length range
sed -r "/^[a-z]{${2:-5},${3:-8}}$/!d" "$dict_path" > /tmp/mnemonic-words
word_count=$(wc -l < /tmp/mnemonic-words)
# print estimated entropy per word
echo Estimated entropy: $(echo "l($word_count)/l(2)*$1" | bc -l | sed 's/\..*//') bits \($word_count candidate words\)
# get number of potential words, some entropy, and desired number of words, to feed awk
awk -vDICT_LENGTH=$word_count -vRANDS=$(tr -dc 0-9 < /dev/urandom | head -c$[$1*10]) -vCOUNT=$1 '
# get random ints from the entropy, then modulo word list length to find random line numbers
BEGIN{for(;COUNT--;){rands[substr(RANDS,COUNT*10,COUNT*10+10)%DICT_LENGTH]=1}}
# only print selected lines
rands[NR]' /tmp/mnemonic-words \
| sort -R | tr '\n' ' ' # sort randomly and put onto one line
# clean up
rm /tmp/mnemonic-words
@markasoftware
Copy link
Author

Should be cryptographically secure, uses /dev/urandom as a source of entropy (and so does sort -R as well as shuf, by default). I'm not sure if entropy estimation is 100% correct. As a rule of thumb, I'd want at least 64 bits of entropy for most things, and at least 128 if you're paranoid or securing something that can be brute forced very efficiently. Needs a dictionary wordlist to be installed, I think most distros come with one? Not sure about mac.

Example output:

$ mnemonic.sh 5
Estimated entropy: 75 bits (37538 candidate words)
breaking avenues hombres forbears eviler 
$ mnemonic.sh 15
Estimated entropy: 227 bits (37538 candidate words)
crabbing nachos midlands viaduct ethics seasides lacks rares snagging sandbank boxiest electron gloats raises clewing 
$ mnemonic.sh 5 15 20
Estimated entropy: 50 bits (1085 candidate words)
interdenominational acknowledgments contextualization obstructionists maladministration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment