Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] zsh/random module [UPDATED]




On 11/18/2022 10:23 AM, Stephane Chazelas wrote:
I should point out first that I'm not a zsh maintainer. I have
been using zsh daily for over 25 years though, and have been
following this ML on and off for a few years.

I should also point out that I've not read the past discussions
about your module. Sorry if I'm repeating points that have been
made earlier.

Thanks for contributing to zsh, it's always good to get more
hands on it!

In this instance though I'm not particularly convinced that that
new module is particularly needed.

We already have $RANDOM and $(( rand48() )). Most if not all of
the systems I've ever used had /dev/random / /dev/urandom
RANDOM and rand48 are predictable and low quality.

You can already read n bytes from them with:

set +o multibyte
read -ru0 -k20 bytes < /dev/random

or

sysread -s 20 bytes < /dev/urandom

Split into individual bytes in an array with:

array=( ${(s[])bytes )

convert those from/to decimal/octal/hexadecimal with printf or
the # flag or #/## arithmetic operators:

hex=(); printf -v hex %02x \'$^array

For instance or:

set -o extendedglob
hex_string=${bytes//(#m)?/${(l[2][0])$(([#16] #MATCH))}}

So it seems the functionality of that module could be
implemented in a few lines of zsh. Likely less efficiently and
more awkwardly, but maybe adding capabilities to decode bytes
(a la perl's pack/unpack) would be more useful and could be used
for other things than /dev/random.

Some comments about the API:

   -c COUNT
        Sets the number of returned random data.  Defaults to 8,
        unless -i, -L, or -U is specified without -a, in which case
        the default is 1.  COUNT must be between 1 and 64.
Why those arbitrary limits? Why not from 0 to inf?

the getrandom function only guarantees 256 bytes.  64 32-bit integers.  Allowing 256 uint8 would be possible, but harder to explain and doesn't work well with bounding.  As the difference between the lower and upper limit surpasses half the max, the number of bytes thrown away to allow uniformity of distribution becomes unwieldy.

Also zero would not be particularly useful :)


Without -i you get uint8 in hex and with -i uint32 in decimal.
Why the different bases?

It's possible to break a hex string into bytes in a rather straight forward way.   A string of decimal numbers not so much, but decimal numbers are easier to manipulate.

If I didn't think it should do *something* when given no arguments, I'd eliminate the hex string altogether.

Why limiting the bounds to unsigned 32
bits when zsh arithmetic is in signed 64 bits?
compatibility with SRANDOM in bash.  Return size of arc4random. Reducing maximum count to 32.

Other than that, it looks good to me.

Trying to use it to get a random word with it, I came up with:

$ set -o extendedglob
$ l=({A..Z} {a..z} {0..9} _)
$ getrandom -a a -c20 -L1 -U$#l
$ echo ${(j[])a//(#m)*/$l[MATCH]}
EMhKvFuQlmCVSuet5uh0

Doing it straight by reading /dev/urandom would have been a lot
more awkward. Could that be improved/simplified?
It could be done, but a list of acceptable characters would need to be agreed upon and documented.  Are symbols acceptable?  About half of passwords require them, but only accept certain ones and that differs from website to website.





Messages sorted by: Reverse Date, Date, Thread, Author