Comment Re:Responses (Score 1) 251
You don't encrypt the UUID. It's just a verification to make sure they know the UUID, which is universally unique, generated by you, and sent only to your database and to their email address. All this does is establish that they have access to the email address they supplied. If you do as I suggest and tie this UUID directly to the user entry, an attacker can't do anything with this UUID without ALSO knowing the user's login and password. Clicking the unique link or knowing the UUID is useless unless you can also login as the user to access their row in the user table.
For password resets, you generate a random password and salt, set it to immediately expire, and then tell the user that password. You leave the old hash and salt in place - the new stuff goes in separate columns until the switch is done by the user. This prevents users from being unable to authenticate if an attacker merely requests a reset, or if you trigger an expiration due to whatever policies you have in place.
Your login page should authenticate the user (using the original password OR the new temporary one). If the user used their old password and authenticated successfully, you can ignore the reset. If they used the temporary password, block all authorization until a new password is supplied by the user (only let them get to the password reset page).
On the password reset page, ask for a new password. Double check hash(newpass+oldsalt) against the stored temporary hash (do the same for the old regular hash too, if you want). If it's a match, the user is dumb and entered the temp (or old) password. If it's not, you generate a new salt and store hash(newpass+newsalt), store newsalt, reset the password expiration date, blow out the temp password, etc.
The trick here is telling the user the temporary password. This is often done with a unique link (using another UUID) that automatically skips the authentication portion and goes straight to the password reset portion for that user. This is extremely fucking dangerous because anyone with access to the email address can hijack the user's account. Despite this, this is how most site on the internet do it. Sending the temporary password in plaintext or not makes no difference because sending the link in plaintext is functionally equivalent. Your security at this point is hoping the legitimate user made the request, is the only one with access to the email address, and the narrow time window in which the temporary password / reset link is valid.
Security questions, pin numbers, RSA clocks, text messages, heuristics (matching IPs, browsers, etc.) all provide more security, but are useful against a MITM attack or cover the scenario where a user forgot the security answer, doesn't know their pin, lost the RSA clock (dongle or phone), changed phone numbers, moved, etc.