Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Please don't use $RANDOM or $((RANDOM)) or standard `shuf` for password generation. These RNGs are not cryptographically secure. Use input from /dev/urandom instead.

Modulo operations like these are another thing to avoid. To get equal chances for each word, the simplest thing to do is e.g.

    do
      wordlistlength = 10e3
      randomnumber = os.urandom(1) * 256 + os.urandom(1)
    while randomnumber > wordlistlength
    return wordlist[randomnumber]
(Adjust if your list length is greater than 255×256+256, of course.)

Further, I see that cracklib-small is 52k words. That's not good or bad, but it makes the default 4-word phrase 52e3⁴ ~ 63 bits of entropy, which isn't terrible but in my opinion on the short side as a default. It will be perfectly fine if you only ever want to defend against online attacks, but in some cases (think disk encryption or password manager) offline cracking should be kept in mind and for the rest you should usually use a password manager anyhow (so then memorability doesn't matter).

Or perhaps more succinctly: please don't roll your own crypto.

I understand that this is of course very unlikely to be abused if it's just for yourself and nobody knows of this weakness in your credentials (security through obscurity works... until it doesn't), but one day someone will use this as inspiration or it will spread somehow, say through an HN comment... just use good password generators or at least keep insecure ones secret.

Btw: many standard Debian(-based) installations have /usr/share/dict/words available so you don't need an extra install; I haven't seen cracklib used before but that might just be me.



I'm curious. What kind of attacks do you open yourself up to if you use $RANDOM in this situation?

Also, why do we avoid modulo operations?


$RANDOM has low entropy, a predictable sequence and it's even more predictable if you use modulus.

$RANDOM provides 15 bits of randomness (32768 possible values) from an LCG[1] - https://en.wikipedia.org/wiki/Linear_congruential_generator

LCGs are multiply followed by add followed by modulus, which is usually implied by a mask or a native word bit length rolling over. You should observe that multiplies have patterns in the lower digits which an add will only offset, and the modulus will only throw away high bits rather than mix them back in to the low bits. Consider the low digit in multiples of 7 (what you'd get picking a number between 0 and 9 inclusive via modulus):

    7 -> 7
   14 -> 4
   21 -> 1
   28 -> 8
   35 -> 5
   42 -> 2
   49 -> 9
   56 -> 6
   63 -> 3
   70 -> 0
   77 -> 7
   84 -> 4
   91 -> 1
   98 -> 8
  105 -> 5
  112 -> 2
  119 -> 9
  126 -> 6
  133 -> 3
  140 -> 0
The lowest digit has the sequence 7418529630 repeating, which isn't very random. Modulus preserves low order bits and throws away the magnitude of the number. The result is that if you want to get half-decent low-valued random numbers from an LCG, you should take x/range * limit rather than %. You can do this with integer arithmetic via multiply and shift if you have an integer twice the size of your LCG.

But again, don't use an LCG for generating your password.

[1] I looked at the source. Bash looks like it tries to use random(3) if it's available, otherwise it seems to use this, which doesn't have an add:

  x(n+1) = 16807 * x(n) mod (m)




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: