tags:

views:

349

answers:

2

I want to allow users to validate their email address by clicking on a link. The link would look something like

http://www.example.com/verifyemail?id=some-random-string

When I am sending this email, I want to be able to easily generate this 'some-random-string' from row id of user, an integer. and when user clicks on this link, generate that integer back.

Only requirement is this 'some-random-string' should be as opaque and non-guessable to the user as possible.


Finally, this is what I settled on

def p3_encrypt_safe(plain, key):
    return base64.urlsafe_b64encode(p3_encrypt(plain, key))

used the nice crypto library from http://www.nightsong.com/phr/crypto/p3.py addition of base64 safe encoding is mine.

+3  A: 

Use encryption, that's exactly what it's designed for. Blowfish, AES, even DES3 if you don't need particularly high security.

Alternatively, you could compute an SHA-256 or SHA-512 (or whatever) hash of the email address and store it in a database along with the email address itself. That way you can just look up the email address using the hash as a key.

David Zaslavsky
An SHA hash of an ID is slightly easier to deal with than an encrypted ID. Save all the hashes in your database and compare the hash you get with one of those.
S.Lott
+5  A: 

Your best choice is to generate a hash (one-way function) of some of the user's data. For example, to generate a hash of user's row id, you could use something like:

>>> import hashlib
>>> hashlib.sha1('3').hexdigest()
'77de68daecd823babbb58edb1c8e14d7106e83bb'

However, basing your pseudorandom string only on a row id is not very secure, as the user could easily reverse the hash (try googling 77de68daecd823babbb58edb1c8e14d7106e83bb) of such a short string.

A simple solution here is to "salt" the hashed string, i.e. add the same secret string to every value that is hashed. For example:

>>> hashlib.sha1('3' + '[email protected]' + 'somestringconstant').hexdigest()
'b3ca694a9987f39783a324f00cfe8279601decd3'

If you google b3ca694a9987f39783a324f00cfe8279601decd3, probably the only result will be a link to this answer :-), which is not a proof, but a good hint that this hash is quite unique.

DzinX