Skip to content

Instantly share code, notes, and snippets.

@atoponce
Last active November 12, 2019 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atoponce/34fe37853c93df33ff03b00503c208d1 to your computer and use it in GitHub Desktop.
Save atoponce/34fe37853c93df33ff03b00503c208d1 to your computer and use it in GitHub Desktop.
32-bit uniform random number generation in the shell in the range of [1, n]

The following shell scripts pass POSIX compiance with posh(1) on Debian. They have also been tested in bash(1), ksh(1), and dash(1) (which provides /bin/sh) on Debian.

Feedback of testing with other shells on other systems to target portability is greatly appreciated. I don't get notified of Gist comments, so reach out to me on Twitter instead.

Execute with an argument as a maximum random number, no bigger than 4294967296:

$ ./insecure-random.sh 100
81
$ ./secure-random.sh 100
17
#!/bin/sh
# POSIX compliant
m="$((4294967296 - (4294967296 % $1)))"
while
r="$( (date +"%s"; who -a; ps -aef; df -P; env) 2>&1 | cksum | awk '{print $1}')"
[ "$r" -gt "$m" ]
do :; done
echo "$((($r % $1) + 1))"
#!/bin/sh
# Not POSIX compliant, due to /dev/urandom
# I don't know how to get to a CSPRNG in POSIX
m="$((4294967296 - (4294967296 % $1)))"
while
r="$(dd if=/dev/urandom count=4 2>&1 | cksum | awk '{print $1}')"
[ "$r" -gt "$m" ]
do :; done
echo "$((($r % $1) + 1))"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment