PHP Manual Masterpieces

Nov 3

So PHP. Such Documented

So some infosec acquaintances of mine have dropped a random seed cracker for PHP’s mt_rand() - that is, given a good sample of the random output, determine what the original seed input was, and thereby recreate the entire random stream. Depending on the application, this could be used to crack encryption, cheat at games, et cetera. The fact that it is possible to do in a reasonable timeframe is kind of worrying in and of itself but that is besides the point. The point is PHP is a mess.

What is mt_rand()? The “mt” stands for "Mersenne Twister" because we should be building the name of the underlying algorithm directly into the namespace and forcing consumers of the API (you) to sit around saying “which version of rand() should I be using?” Fortunately, the documentation is here to help us decide!

mt_rand — Generate a better random value

Better than…?

Many random number generators of older libcs have dubious or unknown characteristics and are slow. By default, PHP uses the libc random number generator with the rand() function. The mt_rand() function is a drop-in replacement for this. It uses a random number generator with known characteristics using the Mersenne Twister, which will produce random numbers four times faster than what the average libc rand() provides.

This is such the most PHP thing. Most languages, I think, would do the exact opposite thing when faced with this problem: they would change the implementation of rand() to a known good one and shuffle off the old version to old_rand() if you absolutely needed to keep the old, platform dependent one (ie the seed stream was not portable between machines anyway). But no! Why do that when you can leave the bad one in place at the obvious name and implement the good one with an awkward name?

But of course, the documentation of rand() will clearly point out that it’s effectively deprecated and one should always use mt_rand(), right?

Nah. Sounds like a lot of work. Stuffing it in “See Also” should do the trick.

A quick look on github suggests that whether people use rand() or mt_rand() is about 50/50. And mt_rand() isn’t “cryptographically secure” anyway - for that you need OpenSSL! Github shows about ten thousand results for that versus about a million results for rand()/mt_rand().

I literally almost fell out of my chair laughing when I saw the awkwardness of this design and the asymmetry of the documentation. This sort of namespace clutter is just the most PHP thing.