views:

377

answers:

4

I'm writing my own sessions controller that issues a unique id to a user once logged in, and then verifies and authenticates that unique id at every page load. What is the most secure way to generate such an id? Should the unique id be completely random? Is there any downside to including the user id as part of the unique id?

A: 

The best way would be to generate a UUID, using the uuid.uuid1 function:

Generate a UUID from a host ID, sequence number, and the current time.

Andrew Hare
Would this be the host ID of the machine on which the script is running? Or of the connecting user? How does the host id get specified? Thanks.
ensnare
Having constant factors (like a host ID) or predictable factors (like a sequence number) is not what you want for this application. uuid.uuid4 may be more suitable, depending on implementation. Also, the UUID is a string expressed in hexadecimal, and you can more entropy-per-byte if you use a wider range of characters.
keturn
+1  A: 

Use the UUID module in 2.5 and higher. This way they can't be guessed since they are not sequential. If you want them to be really secure you could salt them with the user's id and then SHA1 hash them, Base64 encode the result and then use that as the value. That way you could verify on the server side that they really are your cookies and not just something that some spammer is generating and throwing at your server. And to make them even more secure make sure they only last for a set amount of time on the server as well as the client. Python 2.6.5 has an HMAC implemenation built in that you could use on the generated UUID as well.

fuzzy lollipop
How do you do this server-side verification of the hash? And what does that buy you again? This seems a misleadingly complex way to come up with some random bytes.
keturn
Using an HMAC allows the server to verify that it generated the random value without having to store that random value. It can also include a timestamp to allow for expiration of the token, and the client can't modify that timestamp without invalidating the HMAC. This *is* more complex, but allows you to validate that token without hitting a database.
retracile
I should probably also mention that in the HMAC case, the random value only needs to be a nonce. But that's what the books are for -- they cover this much better than I ever could. :)
retracile
+2  A: 

Go buy Bruce Schneier's Secrets and Lies and his Practical Cryptography. Go ahead and order Ross Anderson's Security Engineering 2nd Ed. while you're at it. Now, read Secrets and Lies -- trust me, it's a fun read. :) Then read Practical Cryptography. At that point you should have a better grounding in what you need to do when implementing software that needs some security. Go ahead and do your rough-draft implementation. Now that your copy of Security Engineering has arrived, read it... though that one you may want to digest a bit slower; it's a rather heavy tome.

There is also a whitepaper on web authentication dos and don'ts that is worth reading and a bit more directly applicable to what you're doing. I still recommend the books above.

And another timely article from LWN.net which lists a good number of pitfalls you need to work to avoid. (BTW, LWN.net is well worth subscribing to, and I highly recommend it. The above link allows free access to that article which otherwise would not be available to non-subscribers yet.)

retracile
+2  A: 

If the only information in the cookie is an identifier, essentially a label, the only attack you're trying to protect from is an attacker guessing what it is. So use some random bytes. Enough random bytes that it's "unguessable."

Then squish the random bytes into something that fits within the confines of which characters you can use in a HTTP cookie. base64 works for this. It's not absolutely optimal, because there are more than 64 cookie-safe characters and it tends to leave trailing == characters which add bytes to the header but not randomness, but that's fine. It works and Python can probably do the base64 encoding faster than anything else we can come up with.

If you also want to prepend the user ID to it, that will make things easier to trace and debug, which will probably make your life easier, so go ahead. It doesn't give an attacker any significant advantage. (unless they manage to steal one without being able to otherwise determine what user they're stealing from, which seems unlikely.)

keturn
Make 100% certain that the cookie *never* goes over plain HTTP; if it can be intercepted, "unguessable" is no longer a factor. Again, I recommend doing some real reading on the topic...
retracile
Largely true. But only a small fraction of the world is in a position to intercept packets. Whereas you can use a whole botnet anywhere in the world to make guesses. But, yeah, if you don't want to screw over anyone using a poorly secured wifi hotspot, get HTTPS and a valid cert.None of that has any particular bearing on cookie generation, however.
keturn