2

What is the best way to generate random numbers in Solaris?

I can not seem to find a good answer for this. Most results do not work in my environment. There is a variable or command RAND that seems logical it would work in some manner similar to $RANDOM which I see in most of my searches but it always produces 0.

I have found this command

od -X -A n /dev/random | head -2

Which seems very random but the return format is odd (to me).

     140774 147722 131645 061031 125411 053337 011722 165106
     066120 073123 040613 143651 040740 056675 061051 015211

Currently using:

-bash-3.2$ uname -a
SunOS XXXXXXXXX 5.10 Generic_150400-29 sun4v sparc SUNW,SPARC-Enterprise-T5120
  • 1
    bash and ksh (among others), even on Solaris, provide $RANDOM, which you can use for a random integer between zero and one less than a modulus. For example, $[${RANDOM}%5] will resolve to a random number between 0 and 4, inclusive. Note that sh does not provide $RANDOM. – DopeGhoti Nov 23 '15 at 23:20
6

$RANDOM is available in ksh and in bash, but not in /bin/sh. The value is a random number between 0 and 32768, and is not suitable for cryptographic use.

Reading from /dev/random generates a stream of random bytes which is suitable for cryptographic use. Since these are arbitrary bytes, potentially including null bytes, you can't store them in a shell variable. You can store $n bytes in a file with

</dev/random dd ibs=1 count=$n >rnd

You can use od to transform these bytes into a printable representation using octal or hexadecimal values. If you find the output “strange”, well, maybe you should pick different od options.

Another option to obtain a printable representation is to call uuencode to produce Base64:

</dev/random dd ibs=1 count=$n | uuencode -m _ | sed -e '1d' -e '$d'
  • Well, if you're going to implement cryptography in shell, you're doomed anyway :-) – Wouter Verhelst Nov 24 '15 at 1:17
  • @WouterVerhelst You might want to generate a key from a shell script, and pass it to some other command that does cryptography. The random value might also be something that isn't directly involved in cryptography, but needs to be unpredictable, such as a password/cookie of some kind. /dev/random is suitable for that, $RANDOM isn't. – Gilles Nov 24 '15 at 1:23
  • This is getting way off topic, but no. Generating a key involves much more than 'just' random numbers, and doing it in shell is a terrible idea. There are certainly reasons why you might want to use /dev/random in a shell script, but cryptography is not one of them. – Wouter Verhelst Nov 24 '15 at 9:27
  • 1
    @WouterVerhelst I write cryptographic software for a living, and it is my professional opinion that there is nothing wrong with generating a cryptographic key by retrieving bytes from /dev/random with a shell script. (There are of course plenty of ways to do that wrong, or to misuse the key, but the fundamental approach is sound.) – Gilles Nov 24 '15 at 10:33
  • @Gilles I am not sure what the issue is with the server I am working on, but yesterday echo $RANDOM was producing null / blank values. Today it appears to be working fine. This makes me nervous about making a script that relies on it so I appreciate you looking into the other option. Thanks! – JaredTS486 Nov 24 '15 at 15:15
1

This are three ways to get n bytes, expressed as 2*n Hexadecimal digits:

#!/bin/bash
n=64
# Read n bytes from urandom (in hex).
xxd -l "$n" -p                    /dev/urandom | tr -d " \n" ; echo
od  -vN "$n" -An -tx1             /dev/urandom | tr -d " \n" ; echo
hexdump -vn "$n" -e ' /1 "%02x"'  /dev/urandom ; echo

Reading from urandom (and Please, do use urandom).

The hex digits may be redirected to a file or stored in a variable:

 a="$(xxd -l "$n" -p /dev/urandom)"

And you could get the original bytes using xxd, as simple as:

## Warning, this produces binary values

echo "$a" | xxd -r -p      # If the Hex digits are in a variable.
xxd -r -p "$rndfile"       # If the Hex digits are in a file.

If xxd is not available, and assuming the hex digits are in $a.
You could use this bash code:

#!/bin/bash

>"$rndfile"                            # erase the file

for (( i=0; i<${#a}/2; i++ )); do      # do a loop over all byte values.

    # convert 2 hex digits to the byte unsigned value:
    printf '%b' $(printf '\\0%o' "0x${a:$i*2:2}") >> "$rndfile"

    b="${b#??}"  # chop out two hexadecimal digits.

done

Or you may try this sh compatible code (should run in bash comfortably). Yes it should be sh compatible. Report if you find problems.

Only tested in dash (but should run in some others).

#!/bin/sh

i=$((${#a}/2))          # The (length of $a ) / 2 is the number of bytes.
b="$a"                  # use a temporal variable. It will be erased.
: >"$rndfile"           # erase file contents

while [ $i != 0 ]; do

    # Write one byte transformed to binary:
    printf '%b' $(printf '\\0%o' "0x${b%"${b#??}"}") >> "$rndfile"

    b="${b#??}"  # chop out two hexadecimal digits.
    i=$((i-1))   # One byte less to finish.

done
0
</dev/random \
dd bs="${num_len}" count=1 | LC_ALL=C \
tr -c 0-9 "$(printf '[%d*24]' 9 8 7 6 5 4 3 2 1)[0*]"

that ought to work well for base 10 and wastes nothing, though the digit distribution is very slightly favored for 0.

with Solaris v<11 you'll want to use ` backticks rather than $(...) for the command substitution.

  • You could remove the last 6 possible values to get 250 possible values, divisible by ten. Then, the distribution is fully uniform. Use an aditional tr filter : tr -d '\372-\377' . – user79743 Nov 25 '15 at 19:49
  • @BinaryZebra - i don't understand what you mean about entropy, really, but i'm no crytpographer. i am aware of the distribution issue, which is why i mentioned it. and no, my tr cannot be shortened in that way. i have written other answers on this website to similar purpose. this is far better than what i generally see people do, which is tr -dc 0-9 </dev/random | dd bs=... count=1 which is horribly wasteful. i know that i use all of the bytes, but i don't know much about the rate of universal decay. – mikeserv Nov 26 '15 at 0:47
  • @BinaryZebra - openssl is not anything like an efficient random number generator. and yes, it is far better than what i generally see people do, the most common example of which i've already given. almost every answer at your link is using bash's $RANDOM anyway, which is actually a derivation of $$ and $SECONDS. – mikeserv Nov 26 '15 at 4:28
  • Of the 8 answers at the (piked at random) link, only 2 use $RANDOM. One is just as a second option for the users, the other has 0 votes. That's 1 in 8. So, your comment is very incorrect. .... .... .... If you need the detail of counting, here it is: echo -e "\n\nRamesh\t\t10\ openssl\ urandom \nl0b0\t\t5\ random \njimmij\t\t5\ rand48 \nMalteSkoruppa\t4\ urandom\ \$RANDOM \nJ.F.Sebastian\t4\ python.random\ \ \nterdon\t\t3\ perl.rand\ \ \nFalco\t\t2\ -\ \ \nAdrian\t\t\0\ \$RANDOM" – user79743 Nov 26 '15 at 20:56
  • @BinaryZebra - ok, the very large majority of the text in the answers there concerned $RANDOM. and i still don't get what the problem is with converting a random occurrence in input across a fixed range of distribution. how is that a bad thing? every byte is used, and when you add one to the string you don't add one you append to a string which will be interpreted as a number. this doesn't concern itself with byte values, but rather focuses on maximizing the randomness in input occurrence. – mikeserv Nov 26 '15 at 21:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.