Thread: Random strings

Random strings

From
"Joe Conway"
Date:
> > generating session keys and other things.  It's good to have a
> > choice.  Right now I have a lot of pl/pgsql which calls plain old
> > RANDOM() to generate session keys, and that is not good.  Before I
> > launch this thing, I will need to find a way of getting better random
> > numbers.  If anyone has created a function like that for PG, please
> > mail me, because I need it.
>
> As I said earlier, I just recently created a function for something else
I'm
> working on which returns a binary string from /dev/urandom of whatever
> length you request. I'm using it for initialization vectors (IVs) for 3des
> cbc and for session keys. It should be relatively easy to turn into a
pgsql
> contrib function, so I'll post something to patches within the next couple
> of days. It would not be intended to replace the standard RANDOM()
function,
> just compliment it. Biggest question in my mind is the return type --
should
> it return pure binary as a bytea type, or hex as a text type? Any thoughts
> on this?
>

Per the discussion yesterday, here's a patch. There are two versions of
essentially the same function. They both take an int as the number of
requested random bytes, and generate a random binary string of the requested
length from /dev/urandom. The first one (randomstr_hex) converts the binary
to hex and returns it as text, and the other (randomstr_bytea) does the
needed escaping of special characters and returns bytea.

Let me know if you have any other thoughts on how this can be improved. I
didn't bother to create a function to return a random 0 - 1 interval float
(ala random()) because in most cases where cryptographic quality random
values are needed, the provided forms are the most useful ones (I think).

-- Joe



Attachment

Re: Random strings

From
Peter Eisentraut
Date:
Joe Conway writes:

> Per the discussion yesterday, here's a patch. There are two versions of
> essentially the same function. They both take an int as the number of
> requested random bytes, and generate a random binary string of the requested
> length from /dev/urandom. The first one (randomstr_hex) converts the binary
> to hex and returns it as text, and the other (randomstr_bytea) does the
> needed escaping of special characters and returns bytea.

Perhaps one of these returning bytea would be enough and you can use
the new encode functions to convert them to a format of choice.  Also, why
aren't you using /dev/random?

--
Peter Eisentraut   peter_e@gmx.net   http://funkturm.homeip.net/~peter


Re: Random strings

From
"Joe Conway"
Date:
> > Per the discussion yesterday, here's a patch. There are two versions of
> > essentially the same function. They both take an int as the number of
> > requested random bytes, and generate a random binary string of the
requested
> > length from /dev/urandom. The first one (randomstr_hex) converts the
binary
> > to hex and returns it as text, and the other (randomstr_bytea) does the
> > needed escaping of special characters and returns bytea.
>
> Perhaps one of these returning bytea would be enough and you can use
> the new encode functions to convert them to a format of choice.  Also, why
> aren't you using /dev/random?

Very nice. I hadn't looked encode/decode yet. I'll rework the patch and just
leave the bytea as you suggested.

As far as /dev/random, the issue it that it blocks when it runs out of
entropy. As a small test, I recompiled with /dev/random and tried:

   select randomstr_bytea(8), foo from bar;

where bar has about 120 rows. I was still waiting a minute later. When
requesting one at a time (but resubmitting relatively quickly), it works
fine until about the 35th request in a row, then it blocks briefly (~2
seconds). The same test with /dev/urandom returns instantly. Perhaps there
should be an option to use either. For instances where only a few truly
random bytes is needed (i.e. one session key), use /dev/random. When you
need many random bytes quickly, use /dev/urandom?

-- Joe



Re: Random strings

From
"Joe Conway"
Date:
> > Perhaps one of these returning bytea would be enough and you can use
> > the new encode functions to convert them to a format of choice.  Also,
why
> > aren't you using /dev/random?
>

Here's a revised patch. This one has only one user function, randomstr(int
binlen, text source). It allows any length request (well, limited by int)
against a source of 'urandom', or a maximum of 64 bytes against a source of
'random'. I also added a couple of examples to the readme to show how to use
randomstr() with encode() to get hex or base64 output.

On a side note, in the last version of this, I had a function which escaped
the binary C string so that I could feed it to byteain. In this version, I
decided to populate the varlena struct directly, because it seemed an awful
waste to escape the binary just so that byteain could unescape it. But I'm
not sure this is considered a "good thing", or a "bad thing". I'd appreciate
any guidance.

Thanks,

Joe


Attachment

Re: Random strings

From
Peter Eisentraut
Date:
Joe Conway writes:

> seconds). The same test with /dev/urandom returns instantly. Perhaps there
> should be an option to use either. For instances where only a few truly
> random bytes is needed (i.e. one session key), use /dev/random. When you
> need many random bytes quickly, use /dev/urandom?

Not sure if this is intuitive.  How many bytes is "a few"?  Maybe just be
honest about it and name them randomstr and urandomstr or such.

--
Peter Eisentraut   peter_e@gmx.net   http://funkturm.homeip.net/~peter


Re: Random strings

From
"Joe Conway"
Date:
> > seconds). The same test with /dev/urandom returns instantly. Perhaps
there
> > should be an option to use either. For instances where only a few truly
> > random bytes is needed (i.e. one session key), use /dev/random. When you
> > need many random bytes quickly, use /dev/urandom?
>
> Not sure if this is intuitive.  How many bytes is "a few"?  Maybe just be
> honest about it and name them randomstr and urandomstr or such.
>

In the patch that I sent last night, I explicitly limited /dev/random to 64
bytes. I agree that this is not very intuitive, but for specific purposes,
such as generating a session key for tripledes (24 byte/192 bit random
string yielding 168 bits for a the key) periodically, it is quite useful.
There's a tradeoff here between cryptographic strength (favoring
/dev/random) and application performance (favoring /dev/urandom) that will
vary significantly from application to application. It's nice to have the
option depending on your needs.

Having said that, I'm not married to the idea that we should provide access
to both /dev/random and /dev/urandom. I'd be happy to roll another patch,
limited to just urandom, and renaming the function if you feel strongly
about it. (should we move this discussion back to hackers to get a wider
audience?)

-- Joe