5

As mentioned in the comments of mt_rand() it is weak in security and we should use /dev/urandom instead. My problem is that from urandom I get a binary string.

How do I convert this binary string to 0-9a-zA-Z?

Looks like base_convert() does not work here.

Bojangles
  • 99,427
  • 50
  • 170
  • 208
PiTheNumber
  • 22,828
  • 17
  • 107
  • 180

4 Answers4

3

Just for the record the full function:

function randomFromDev($len)
{
    $fp = @fopen('/dev/urandom','rb');
    $result = '';
    if ($fp !== FALSE) {
        $result .= @fread($fp, $len);
        @fclose($fp);
    }
    else
    {
        trigger_error('Can not open /dev/urandom.');
    }
    // convert from binary to string
    $result = base64_encode($result);
    // remove none url chars
    $result = strtr($result, '+/', '-_');
    // Remove = from the end
    $result = str_replace('=', ' ', $result);
    return $result;
}
PiTheNumber
  • 22,828
  • 17
  • 107
  • 180
2

You can use bin2hex for the binary to string conversion. And PHP 7 random_bytes added urandom lookup.

<?php
$bytes = random_bytes(5);
$str = bin2hex($bytes);
var_dump($str);
// string(10) "385e33f741" 
?>
SamGoody
  • 13,758
  • 9
  • 81
  • 91
1

just use base64_encode($yourbinaryurandomstring)

with that result you can e.g. use a hash function like sha1() or md5() and should be fine. You don't even have do do any conversion of "="

I'm not quite sure if the hash functions can read a binary string for their own, just give it a try.

evildead
  • 4,607
  • 4
  • 25
  • 49
  • Thank you! Naa, no hash function for me today. Just had that [topic](http://stackoverflow.com/questions/8427999/generate-shorter-public-id/8428368#8428368) ;) – PiTheNumber Dec 08 '11 at 11:06
1

One way of using /dev/urandom is the function uiniqid which should fit your needs.

However, if you need true random numbers you should better use /dev/random as /dev/urandom is still a pseudo random number generator which use /dev/random for seed values.

Accessing the random number stream is not that hard.

<?php
$r = unpack('v*', fread(fopen('/dev/random', 'r'),16));
$uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
    $r[1], $r[2], $r[3], $r[4] & 0x0fff | 0x4000, 
    $r[5] & 0x3fff | 0x8000, $r[6], $r[7], $r[8]);
?>

Obviously this is not production code.

Mythli
  • 5,995
  • 2
  • 24
  • 31
  • A cryptographically-secure PRNG is still useful for crypto. And whether or not `/dev/random` gives you its actual entropy pool depends very much on the OS. In FreeBSD both are the same, using Yarrow. – Joey Dec 08 '11 at 11:37
  • 1
    Yes I knowed the first part but I don't want to bloat my answer that hard. – Mythli Dec 08 '11 at 11:40
  • Concerning `uniqid()`: "This function does not create random nor unpredictable strings. This function must not be used for security purposes. Use a cryptographically secure random function/generator and cryptographically secure hash functions to create unpredictable secure IDs." (from the PHP doc) –  May 12 '15 at 21:18
  • `/dev/urandom` is not pseudo, unlike `rand` or `mt_rand`. In the worse case it creates random number from a truly random pool which is constantly refreshed. Most of the time it is exactly as good as `/dev/random`. – Sheepy Jul 02 '15 at 06:12
  • /dev/random is not _more_ random, /dev/random and /dev/urandom use exactly the same CSPRNG. For a good read see: http://www.2uo.de/myths-about-urandom/ – harmv Mar 07 '16 at 11:57