How not to create a Random string


It is surprising to see how after all the code floating around people still find it hard to create random numbers. In a recent piece of code I encountered, the following was used to generate a string of random numbers. The code was written to provide a random string to be passed to a email verifier system – the type wherein a new user when he subscribes to a website needs to verify his email by clicking on a provided link.

The verification code was created by the following lines.

$alphanum  = "123456789";
 
# $insertedId is the id of the last database insert
# $verification_code is saved in the database
$verification_code = (substr(str_shuffle($alphanum), 0, 5)) . $insertedId;
 
# Good till here, but the following line botches it up,
# the generated number is further multiplied by a constant.
$verificationCode  = $verification_code * (12345) #ouch!;

# $verificationCode is now sent through the email link as a GET parameter,
# e.g http://www.xyz.com/verify_email.php?vid=$verificationCode

When the user clicked on the verify email link the verification code was retrieved from the GET parameter, divided by a constant number and the result compared to the original verification code stored in the database.

$verificationCode = $_GET['vid'];
$verifyCode = $verificationCode / 12345;

The problem was that once in a while the random string generation code would spew a somewhat larger number, which PHP would happily convert to a exponential format and pass it over the email link in the GET parameter.

http://www.xyz.com/verify_email.php?vid=6.9833696969697E+19

The number which when retrieved by the system would obviously not compare with the original and the system would flag the email link as invalid, robbing the site owner of potential subscribers.

Rather than go with all the rigmarole, a good way would have been to generate a random string using the following.

$verificationCode  =  md5(uniqid(rand(), true)) . time();

The point being that you cannot be too careful when dealing with numbers, a single overlooked fact can trip you.

This site is a digital habitat of Sameer Borate, a freelance web developer working in PHP, MySQL and WordPress. I also provide web scraping services, website design and development and integration of various Open Source API's. Contact me at metapix[at]gmail.com for any new project requirements and price quotes.

5 Responses

1

Christian South

November 26th, 2010 at 9:50 am

Nice post. I think this is where UUIDs work wonders. I have worked with a couple of sites where the verification code sent to the users email address was just their UUID in the databases. Because of the nature of UUIDs I find the the semi-random nature of their generation is enough to counteract most if not all of the brute forcing effects. Also if all your using it for is user verification (and still requiring the user to login after verification) it doesn’t matter how many accounts the potential hacker activates.

2

memor

November 26th, 2010 at 1:15 pm

To nit-pick:

It was also a mistake to use str_shuffle, because it reduces the number of possible values.
10*9*8*7*5 instead of 10^5 in this case.

3

Peter Smit

November 28th, 2010 at 11:28 pm

Why would you still append the time to uniqid(rand(), true)? Uniquid already contains the time (in miliseconds).

sameer

November 28th, 2010 at 11:35 pm

In a rare case if md5 generates a collision, the appended time() will make it unique.

5

Programowanie w PHP » Blog Archive » Sameer Borate’s Blog: How not to create a Random string

June 20th, 2011 at 1:10 am

[...] this latest post to his blog, Samer Borate talks about how not to create random strings and how, if you’re not [...]

Your thoughts