4 ms·
This inspired me to write a rudimentary version in bash/C: ----pwgen.sh #!/usr/bin/env bash DICT=/usr/share/dict/words NL=$(wc -l $DICT | sed '
by arh68 12y ago
This inspired me to write a rudimentary version in bash/C:
----pwgen.sh
#!/usr/bin/env bash
DICT=/usr/share/dict/words
NL=$(wc -l $DICT | sed 's_[ \t]*\([0-9]*\).*_\1_')
PW=""
for i in {1..4}; do
RAND=$(./arc4random)
LINE=$[$RAND % $NL]
WORD=$(sed -n $LINE"p" < $DICT)
PW=$WORD" "$PW
done
echo $PW
----arc4random.c
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("%u\n", arc4random());
return 0;
}
They're not always easy to remember, though, at least for me:
> ./pwgen.sh
interdepartmental anesthyl intrabranchial physiolatrous
- cynwoody 12y agoYour little script performs amazingly well on my Mac, coming in at about 165 ms, quite a bit faster than I expected. If your script is too fast for you, you could consider reading the dictionary into a bash array instead of using sed. My /usr/share/dict/words contains 234,936 words. As a point of comparison, here is a Python version that clocks in around 107 ms: #!/usr/bin/env python from random import SystemRandom as r with open('/usr/share/dict/words', 'rb') as f: lines = f.readlines() print ' '.join(r().choice(lines).rstrip() for x in xrange(4)) However, I don't know how well SystemRandom compares to arc4random in terms of crypto.
- jzwinck 12y agoIf you're set on using arc4random it's no big deal to use ctypes to invoke it from Python. Bash is quick to bang out but it's funny how your parent needs to compile a C program then invoke it N times per bash script run. Using Python for this is an obvious choice.
- arh68 12y agoYes thanks for pointing that out, I wrote a slightly faster version below. I took your advice and wanted just a single invoke on the C program, so I modified it to take an argument. I'm satisfied! > cat arc4random-v2.c #include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { if ( ! (argc == 1 || argc == 2) ) { printf("usage: %s [n_output]\n", argv[0]); } else { int n_iter = (argc == 2) ? atoi(argv[1]) : 1; for (int i = 0; i < n_iter; i++) { printf("%u\n", arc4random()); } } return 0; } > ./arc4random 3 4282823399 333796506 762478899 > cat pwgen-v2.sh #!/usr/bin/env bash dict=/usr/share/dict/words n=4 # of words to include in passphrase nl=$(wc -l $dict | sed 's_[ \t]*\([0-9]*\).*_\1_') fmt_flag() { echo $[$1 % $nl] | sed -n -e 's_^_-e _' -e 's_$_p_p' ; } flags=$(./arc4random $n | while read -r i; do fmt_flag "$i"; done) words=$(sed -n $flags < $dict) echo $words > time ./pwgen.sh liparite evade retiringly spacious real 0m0.268s user 0m0.251s sys 0m0.015s > time ./pwgen-v2.sh latherin prideling thumbscrew unraveled real 0m0.082s user 0m0.072s sys 0m0.013s EDIT: note that the single call to sed results in alphabetical/dictionary-dependent results... (!) oops