Thread: Random strings
> > 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
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
> > 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
> > 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
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
> > 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