The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

well what about this, You email them a link to a page where they can reset there password. Of course you'll need some kind of validation on this.. so the link contains a random hash that gets generated and stored in your database for that user when they ask to have there password reset. When they go to the reset password page they must have an identifier in the url with his hash code. This should be secure as the user who signed up provided his/her email address. ALso you could provide and expire time like you mentioned.

so you are talking about something like an ISP resetting a users password.. The thing about that is they typically keep financial account separate from users email account, which although its not as convenient for the user, its defintely better. I dont know why you would own a users email address and have there credit card information all in one setting..
Not only that, but typicaly you have to do that over the phone. I dont think the original poster was talking about setting up his own isp or email server.

I'm talking about a user account system - nothing to do with credit cards or anything like that... My point is, emailing a URL for a password reset is a good solution, but not always possible. I actually use a mix of the two - if we have a separate email address on file, we can reset the password that way; if not, they need to answer the security questions.

Use sessions. Thats how I do it, sessions along with md5 encryption. Although I know it is only one way, have you ever thought of encrypting both the actual password, and the password entered (in md5) then comparing the sums? It is basically the same as comparing two decrypted passwords, except if someone was to get their hands on a cookie hash, they couldn't decrypt it.

You can't decrypt a hash. MD5 is a hash... Not encryption. Huge difference.

And session data can be stolen just as easily as cookie data (some would even say easier). There is no added benfit of using sessions over cookies except that you can't have to option to keep your users loggen in if they close the browser. Using a script specific "salt value" + password and MD5'ing the whole thing is good enough for the majority of web aplications.

I do however take back my statement that MD5 on its own is enough. I have run across several brute force MD5 sites that will use some major server processing power to brute force the MD5 up to 8 charecters in a reasonable amount of time to have me worried. But addign in the salt value to the password giving it more charecters to sift through . especially if your salt includes capital letter, lower case letters and numbers/special characters.

Store something like the userid, and a 'verification' cookie which is a hash of the userid combined with a salt. :-)

So, what exactly are you comparing to see if they should be logged in? User ID? Seems even less secure if a user is on 2 computers and changes the password from one computer. The second computer would never know and continue to allow access.

I would suggest to calculate the hash (to save in the db) like md5(md5($pass)) or md5(sha1($pass)) or any other good combination.

The point is, the length of the source string for the outer md5(or sha1) gets higher (32 or 40 from the above; you can also use like md5($p).sh1($p) which would give 72 input chars for the outer hash). So, the brute-force on md5 is less-less-less-likely.

On http://passcracking.com/ , one can crack (now disabled) hashes for input strings with 8 or less chars (a-z;0-9). Don't just save md5($pass).

You can also use base64 on inside hashes for the outer hash input string to have higer key space (a-z;A-Z;0-9;+/). You better use the outer hash with a salt.

$h = md5($b64_innerhash . $my_salt)

Hope this helps.
(I have seen on many places that md5/sha1 are mentioned as encryptions while actually they are hash algorithms)

PS: XtrEM3, "JeffIsGood" is really good.
PS: this is my very first post (on the net)

Good question you've raised here. I've been through this and it requires some client side code to complete the chain. I only use this if I do not have access to SSL encryption. (in that case I am very comfortable using sessions)

It looks like this:

The login page is held in a static frameset. If your page doesn't need a frame you can always create a frameset of one page.

The login page contains a form with fields for the username and password. Instead of submitting those values to the server they are stored as Javascript variables in the static frameset. The "username" value is set in a cookie and the page is reloaded.

The server reads the username and checks if it is a valid user. If it is, it sends back the time. Since time only advances this provides a unique nonce which will never be the same. (a "nonce," also known as a "salt," is a unique value which can be combined with static information like your username and password to create a unique hash) The database records the nonce sent for that user.

The refreshed page contains Javascript which then uses MD5 to hash the username, password and nonce and sets a "loginHash" cookie value. The page is refreshed once more.

The server sees the "loginHash" cookie value as well as the "username" cookie value so it is able to retrieve the password and nonce for that user from the database and also perform an MD5 hash of the username, password and nonce values. If the supplied hash matches the hash of the database values, you have a login.

(If not, it is recorded as a failed attempt. If there are too many failed attempts the account is frozen to prevent brute force or "dictionary" attacks.)

If the login is good a new time-nonce is recorded in the database and sent to the client. A Javascript call appended to the top of every page uses the nonce to create a new "loginHash" for each page request. This helps prevent eavesdropping attacks because an attacker cannot use any of the hashes already transmitted to gain access. This is a serious issue with the current crop of server digest authentication schemes - they allowed previously used hashes to take over sessions!

As was mentioned, if other users are allowed to post content on your pages they may be able to include Javascript to grab the "document.cookie" value. However, once your hash has been sent to the server it is already expired. It does the attacker no good whatsoever. The only thing they can obtain cookie-wise is your username.

Last edited by Trent Reimer; Sep 21, 2005 at 09:44.
Reason: forgot to include signature

If you are storing passwords in any format and you wish to encryt for security purposes, it is best to check the user's value with the encrypted password if it matches then its correct else its incorrect.

If you think this is okay for your purpose then i can assist you with a sample code.