Wow, some dangerous (and some not) misconceptions were said here. Commenting in chronological order (not by severity)
JAB wrote:Would storing a number generated by this be acceptable as far as security is concerned?
$hash = rand(101, 998);
No, this is bad: it has only ~900 possibilities, which are easy to bruteforce.
arjan wrote:$hash = md5(uniqid(rand(), true));
use some hash function, md5, sha1 or go with something better like sha256
In this case, there is little-to-none security benefit in choosing one hash over another, as the entropy of the hash will be no greater than the entropy of the underlying random. uniqid() generates at most 23 hex chars, i.e. 92 bits of entropy. Using a 128 bit MD5 or a 256 bit SHA256 makes no difference, the entropy of the hash will be still 92 bits. (Actually even less, as parts of the uniqid() are based on the system time)
JAB wrote:I'm not sure *why* I want to use a hash? I don't see the advantage over simply using rand.
The point of using a hash function at all is twofold: to disperse the random bits more evenly (non-cryptographic randoms are notoriously bad at this) and to provide an ID of fixed size, both features are actually directed towards easier storage,
not security. As you've correctly observed, there is almost no advantage.
arjan wrote:do not store any user information into cookies
ORLY? Why? And what about your next suggestion in that case:
arjan wrote:what i suggested in my first reply was this:
$hash = md5($username.$email.$userid);
then save this into cookie (for example auto_login) and the user table
Very, very bad suggestion. The username is publicly known, the email is potentially known or guessable, and the userid is also publicly known. The secrecy of the hash depends of the secrecy of the email address of the user, imagine how secure this is. Give me your email, and I'll send you the details personally.
To recap:
1. uniqid(mt_rand(), true) is good enough for a random nonce (mt_rand() is a bit better than rand() ), you may MD5 it for convenience (also MD5 is fast to calculate, so it's almost no additional burden)
2. Checking it against the database is also good enough.
3. You must change it after a valid login, to mitigate (but not completely remove!) the effect of the nonce being stolen.
4. You must not do the check if the user has a valid login (no point in it, it will only strain the server)
The system is then as secure as the possibilities of stealing the nonce (this generally means: if you have XSS holes, the nonce cookie will be stolen from the client, with SQL injection or another attack agains the storage engine, the nonce will be stolen from the server), which is very similar to how secure sessions are in the first place.