I’m not sure the best way to make use of it as a source of random decimals — there are surely a dozen ways to do so — but this works:
printf %d 0x`
head -c 1000 /dev/urandom
| shasum
| head -c 8
`
As always, my advice for things like this is that if you’re in need of true random numbers in your shell script then you should probably stop writing whatever it is you are writing as a shell script.AFAIK it's the go-to source of randomness in any modern-ish unix.
> I’m not sure the best way to make use of it as a source of random decimals — there are surely a dozen ways to do so — but this works:
`od(1)` will do binary data to decimal:
> head -c4 /dev/urandom | od -An -vtu4
4119929390
> head -c4 /dev/urandom | od -An -vtu4
3540752584
> head -c4 /dev/urandom | od -An -vtu4
998126897My favorite tool for this is "openssl rand" and I can find the manual page on rhel7 with "man rand."
Here are 8 bytes of randomness in base64:
$ openssl rand -base64 8
mGHxYcVOmA8=
If you like decimal: $ printf %d\\n 0x$(openssl rand -hex 2)
21924
When I've got dozens of users to create, this is how I am assigning their initial passwords.The shell's $RANDOM is somewhat less trustworthy than other sources here. It also does not appear to be POSIX, but comes from ksh88, where it is described as returning a random integer between 0 and 32767 each time it is referenced. If unset in a script, it cannot be used again for the life of the shell.
function password_generate { head -c ${1-12} /dev/urandom | base64; }This goes from good practice to necessary as a cron job uses increasing resources or talks to a centralized service.
Puppet implements this as splay: https://www.puppet.com/docs/puppet/7/configuration.html#spla...
RD=$(dc -e 16i`xxd -c $N -g $N -l $N -p /dev/urandom | tr a-f A-F`p)https://lwn.net/Articles/889452/
Pragmatically, they are equivalent for most scripting use cases.
The use of "true" here seems ambiguous.
Does this statement mean that you discourage creation of cryptographic applications with shell scripts, you discourage use of shell scripts to orchestrate applications that use /dev/urandom for any reason, or something else entirely?
(first, and only edit: This comment is in good faith, so if you're downvoting please respond to let me know why)
echo "$SRANDOM"
for r in {1..5}; do printf "%s\n" "$SRANDOM"; done
[0] https://www.cyberciti.biz/linux-news/gnu-bash-5-1-released-w...It is also seeded.
echo "rand()" | bc
If you want a bounded integer, use this: echo "irand(<bound>)" | bc
This bound is adjusted to not bias the random numbers.It can also be used to generate either really small or really large integers, arbitrary size. My bc will take care of everything behind the scenes.
If you want to generate a real between 0 and 1, use this:
echo "frand(<places>)" | bc -l
where <places> is the number of decimal places you want. Note the "-l" argument; this function is not built-in like the other two.If you want an arbitrary real (not between 0 and 1), use this:
echo "ifrand(<bound>, <places>)" | bc -l
My bc will seed itself from the system CSPRNG, but you can seed the PRNG by assigning the seed to the special variable `seed` first: echo "seed = $SEED; rand()" | bc
You can even save the current seed by getting the value of the `seed` variable: echo "seed" | bc
If you want to use the same sequence over multiple invocations of bc, you need to save the seed to pass to the next invocation: OUT=$(echo "rand(); seed" | bc)
RAND=$(echo "$OUT" | head -n1)
SEED=$(echo "$OUT" | tail -n1)
RAND2=$(echo "seed = $SEED; rand()" | bc)
(Haven't tried the above code. Sorry if it's wrong.)This pattern works because the `seed` variable is updated after every call to the PRNG.
Does that help?
$ for i in {1..999999}; do echo $((RANDOM-RANDOM)); done | sort -nu | grep -E '^-?.$'
-9
-8
-7
-6
-5
-4
-3
-2
-1
1
2
3
4
5
6
7
8
9I remember learning about the enigma machine and how it had a flaw where a letter could not be transformed into itself. And knowing that, for example, an A could never be a A was critical to cracking the enigma code. Because of that knowledge, my cryptographic intuition is that any seemingly minor fact like this could actually be a critical flaw.
Say you want to generate a strong password, you can use this handy function that works in bash and zsh:
function gen_passwd() {
openssl rand 240 |\
LC_CTYPE=C tr -dc '[:graph:]' |\
cut -c 1-${1:-20}
} karellen@localhost:~$ keepassxc-cli generate -lU
hpJUwcYZnzJyAbrnvTWnTzrlqzqcdvsl
karellen@localhost:~$ keepassxc-cli diceware
diabetes dinginess goldfish purr cried expenses related
See `keepassxc-cli help generate` and `keepassxc-cli help diceware` for more info, or the man page: https://manpages.debian.org/bullseye/keepassxc/keepassxc-cli... sort -R /usr/share/dict/words | head -n 4| sed 's/.*/&/;$!s/$// ' |tr '\n' '-' |sed 's/-$/\n/'I use it for usernames since Bitwarden doesn’t support diceware names.
> I could do more experiments and try to definitively determine what's happening, bottom line, don't use $RANDOM, even for unimportant random numbers.
hexdump -e '"%d"' -n2 /dev/urandom if (( RANDOM % 2 == 0 )); then echo Yes; else echo No; fi
I also logged those decisions. I got significantly more No then Yes. I could never reproduce the bias in a loop. But in real life usage, I got more No. Could be by chance of course. But it made me worried enough that I switched to urandom: bit=$(od -An -N1 -i /dev/urandom)
if (( $bit &1 ))
then echo "Yes"
else echo "No"
firead -r < /proc/sys/kernel/random/uuid
MYRAND=$(( 0x${REPLY%%-*} ))
PORT=$(shuf -i 1000-2000 -n1)
aria2c --listen-port=$PORT ...other...options...
I can only think of one-liners in R or maybe python.
normal_random() {
start=$1
end=$2
range=$(echo "$end - $start" | bc -l)
awk -v start=$start -v range=$range -v seed=$RANDOM '
BEGIN {
srand(seed);
u1 = rand();
u2 = rand();
z0 = sqrt(-2 * log(u1)) * cos(2 * 3.14159265358979323846 * u2);
z1 = sqrt(-2 * log(u1)) * sin(2 * 3.14159265358979323846 * u2);
random_number = start + (z0 * (range / 6)) + (range / 2);
printf("%.0f\n", random_number);
}'
}
In testing it out, they did seem normally-distributed but rerunning it quickly did seem to produce more consecutively duplicate results than would be expected, not sure why that would be (I was using ranges of 0-10 and 0-20, perhaps the probability of normally-distributed consecutive dupes in that range is quite higher?)EDIT: Nope, there's definitely something wrong with this, possibly the rand() call(s)? Can anyone guess? (A real-world example of the perils of relying on chatGPT!) EDIT2: Figured it out. srand with no args seeds to the current second, making any run of this function within the same second produce the same result. Fixing this left as an exercise to the reader EDIT3: I fixed it by seeding it externally via $RANDOM.
`( yes '00' | head -n 100000 | tr -d $'\n') | xxd -r -p | aespipe -e AES256 -P <(echo 'your-seed')`
rand() {
local r4
IFS= read -rk4 -u0 r4 < /dev/urandom || return
local b1=$r4[1] b2=$r4[2] b3=$r4[3] b4=$r4[4]
print $(( #b1 << 24 | #b2 << 16 | #b3 << 8 | #b4 ))
}
It has the added bonus of only using zsh, no external dependencies, so it is quite fast.https://gist.github.com/pmarreck/e65f457e8755e461a87db7c94d4...