I am writing a raffle program where people have some tickets, which are marked by natural numbers in the range of 1 to 100 inclusive.
I use mt_rand(1,100)
to generate the number of the winning ticket, and then this is outputted to the site, so everyone can see it.
Now I did a little research and found out from the Merseene wiki article that:
Observing a sufficient number of iterations (624 in the case of MT19937, since this is the size of the state vector from which future iterations are produced) allows one to predict all future iterations.
Is the current version used by mt_rand() MT19937?
If so, what can I do to make my generated numbers more cryptographically secure?
Thanks in advance :-)
mt_rand
by its very name is the Mersenne Twister, a non secure random number generator. Furthermore it is often just seeded with a specific time in ms, something that an attacker can simply guess or aim for.You cannot make the Mersenne Twister secure. So if anywhere possible you should use a secure random number generator seeded by an entropy source. This entropy source is usually obtained from the operating system. An OpenSSL based one should be preferred.
There is absolutely no reason why you would be stuck with MT. PRNG's are just algorithms. There are plenty of libraries that contain secure PRNG's.
Sorry, but Mersenne Twister was not designed to meet cryptographic requirements. No, you cannot and should not try to fix it, because usually when non-experts try to improve cryptographic functionality, they just end up making things worse.
Php has a long history of problems with its randomness for cryptographic purposes. I'll point out a few references for light reading:
To my knowledge, the best option for secure (pseudo) random number generation in PhP applications is to use openssl_random_pseudo_bytes.
The short answer:
You can simply use a random number generator suited for this task instead of
mt_rand()
.When PHP 7 comes out, you can use
random_int()
in your projects when a cryptographically secure random number generator is needed."Okay, great, but PHP 7 isn't out yet. What do I do today?"
Well, you're in luck, you have two good options available to you.
Use RandomLib. OR
I've been working on backporting PHP 7's CSPRNG functions into PHP 5 projects. It lives on Github under paragonie/random_compat.
"I don't want to use a library; how do I safely roll my own?"
When it comes to cryptography, rolling your own implementation is usually a poor decision. "Not invented here," is usually a good thing. However, if you're dead set on writing your own PHP library to securely generate random integers or strings, there are a few things to keep in mind:
/dev/urandom
should be your first choice, followed bymcrypt_create_iv()
withMCRYPT_DEV_URANDOM
, followed by reading fromCAPICOM
(Windows only), and lastlyopenssl_random_pseudo_bytes()
./dev/urandom
, cache your file descriptors to reduce the overhead of each function invocation./dev/urandom
, PHP will always buffer 8192 bytes of data (which, likely, you will not use). Be sure to turn read buffering off (i.e.stream_set_read_buffer($fileHandle, 0);
).log()
) or anything involving floats.mt_rand()
if no suitable CSPRNG is available; instead, throw an uncaught exception or issue a fatal error. Get the developer's attention immediately.