I have this function for CSRF protection, it is pretty insane.
function GenToken($ranLen) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$()';
$randomString = '';
for ($i = 0; $i < $ranLen; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomString;
}
It is called up by this:
$token = GenToken(rand(32,128));
It uses PHP's rand() which I know is far from ideal when it comes to creating random numbers.
What I am wondering is just how bad is it? Is this function suitable for 'good' (granted wacky) CSRF protection? It sure as hell generates one heck of a string.
Currently the function is only used for CSRF however it could be used for other short random strings like a code emailed to the user to activate their account ect. Is this acceptable?
It'll probably be good enough, as long as the generated tokens are user-specific and/or are expired relatively soon. However, if you're going to change it at all, you should change it to use a decent PRNG, which is available on most systems in the form of /dev/random
and can be accessed using a number of ways:
mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM)
openssl_random_pseudo_bytes($raw_salt_len)
fopen('/dev/urandom', 'r') // then fread enough bytes from it
Simply bin2hex
or base64_encode
the return values of the above. Your rand
(or better mt_rand
) solution should only be a fallback in case none of the above are available.
For the similar task I'd prefer to use built-in php function called uniqid
http://www.php.net/manual/en/function.uniqid.php It should be faster and safer then your implementation