Secure Random Number Generation in PHP

Secure random number generation in PHP

You can also consider using OpenSSL openssl_random_pseudo_bytes, it's available since PHP 5.3.

 string openssl_random_pseudo_bytes ( int $length [, bool &$crypto_strong ] )

Generates a string of pseudo-random bytes, with the number of bytes determined by the length parameter.
It also indicates if a cryptographically strong algorithm was used to produce the pseudo-random bytes, and does this via the optional crypto_strong parameter. It's rare for this to be FALSE, but some systems may be broken or old.

http://www.php.net/manual/en/function.openssl-random-pseudo-bytes.php

Since PHP 7 there is also random_bytes function available

string random_bytes ( int $length )

http://php.net/manual/en/function.random-bytes.php

Generate cryptographically secure random numbers in php

Pseudorandom number generators (PRNG) are very complex beast.

There are no real "perfect" random number generators -- in fact the best that can be done from mathematical functions are pseudorandom -- they seem random enough for most intents and purposes.

In fact, performing any additional actions from a number returned by a PRNG doesn't really increase its randomness, and in fact, the number can become less random.

So, my best advice is, don't mess around with values returned from a PRNG. Use a PRNG that is good enough for the intended use, and if it isn't, then find a PRNG that can produce better results, if necessary.

And frankly, it appears that the mt_rand function uses the Mersenne twister, which is a pretty good PRNG as it is, so it's probably going to be good enough for most casual use.

However, Mersenne Twister is not designed to be used in any security contexts. See this answer for a solution to use when you need randomness to ensure security.

Edit

There was a question in the comments why performing operations on a random number can make it less random. For example, some PRNGs can return more consistent, less random numbers in different parts of the bits -- the high-end can be more random than the low-end.

Therefore, in operations where the high-end is discarded, and the low end is returned, the value can become less random than the original value returned from the PRNG.

I can't find a good explanation at the moment, but I based that from the Java documentation for the Random.nextInt(int) method, which is designed to create a fairly random value in a specified range. That method takes into account the difference in randomness of the parts of the value, so it can return a better random number compared to more naive implementations such as rand() % range.

Generate a Secure Random Integer in Range with PHP 5.6

Might I introduce you to random_compat, which polyfills random_bytes() and random_int() in PHP 5 projects? (Sidenote: among other projects, it's being picked up by Wordpress in 4.4.)

function secure_rand($min, $max)
{
return (unpack("N", openssl_random_pseudo_bytes(4)) % ($max - $min)) + $min;
}

Even if this was doing what you wanted it to do, this is a biased random number generator when ($max - $min) is not an even power of 2.

PHP random string generator

To answer this question specifically, two problems:

  1. $randstring is not in scope when you echo it.
  2. The characters are not getting concatenated together in the loop.

Here's a code snippet with the corrections:

function generateRandomString($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}

Output the random string with the call below:

// Echo the random string.
// Optionally, you can give it a desired string length.
echo generateRandomString();

Please note that this generates predictable random strings. If you want to create secure tokens, see this answer.

Random number in range [min - max] using PHP

<?php
$min=1;
$max=20;
echo rand($min,$max);
?>

PHP Seeded, Deterministic, Cryptographically Secure PRNG (PseudoRandom Number Generator). Is it possible?

Duskwuff asks:

How do you intend to prove that the seed was chosen fairly? A suspicious user can easily claim that you picked a seed that would result in a favorable outcome for specific users, or that you revealed the seed to specific users ahead of time.

Before you investigate solutions, what exactly is the problem you are trying to solve? What is your threat model?


It sounds like you want SeedSpring (version 0.3.0 supports PHP 5.6).

$prng = new \ParagonIE\SeedSpring\SeedSpring('JuxJ1XLnBKk7gPAS');
$byte = $prng->getBytes(16);
\var_dump(bin2hex($byte));

This should always return:

string(32) "76482c186f7c5d1cb3f895e044e3c649"

The numbers should be unbiased, but since it's based off a pre-shared seed, it is not, by strict definition, cryptographically secure.

Keep in mind that SeedSpring was created as a toy implementation/proof of concept rather than an official Paragon Initiative Enterprises open source security solution, so feel free to fork it and tweak it to suit your purposes. (I doubt our branch will ever reach a "stable 1.0.0 release").

(Also, if you're going to accept/award the bounty to any of these answers, Aaron Toponce's answer is more correct. Encrypting the nonce with ECB mode is more performant than encrypting a long stream of NUL bytes with AES-CTR, for approximately the same security benefit. This is one of the extremely rare occasions that ECB mode is okay.)

PHP rand() vs. random_int()

Revisiting the question and seeing there's been an answer given, I find it's only fair that I submit my comments to an answer, seeing they were submitted before.

The manual on PHP 7's random_int() function states:

"Returns a cryptographically secure random integer in the range min to max, inclusive."

  • http://php.net/manual/en/function.random-int.php

and for rand()

*This function does not generate cryptographically secure values" *

  • http://php.net/manual/en/function.rand.php

OP's comment:

"@Fred-ii- thank you. But what does "cryptographically secure pseudo-random" mean? – NDFA"

That can be found in the following links as per my findings:

  • https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator

Which states:

A cryptographically secure pseudo-random number generator (CSPRNG) or cryptographic pseudo-random number generator (CPRNG)[1] is a pseudo-random number generator (PRNG) with properties that make it suitable for use in cryptography.


  • How does a cryptographically secure random number generator work?

In regards to performance, you will need to run a benchmark yourself.

Generate an N-digit random number

Something like this ?

<?php 
$a = mt_rand(100000,999999);
?>

Or this, then the first digit can be 0 in first example can it only be 1 to 9

for ($i = 0; $i<6; $i++) 
{
$a .= mt_rand(0,9);
}


Related Topics



Leave a reply



Submit