These days i’m working on a project with security as main feature. Here’s what i have learned-
Servers should not actually store password, instead a hash of the password should be stored. So next time you see a site which mails you your old password on clicking ‘forgot password’ link, do reconsider giving away your password to that site.
It is important to make your password invulnerable to rainbow tables and birthday attacks . The point is that, it should be impossible to retrieve the password even if your algorithm and password hashes are exposed. The problem with almost all hashes is that they are all optimized to be quick and easy on hardware, and so cracking them share the same qualities. So the best way is to first prepend a salt value to your password followed by repeated hashing of the resultant string with a strong one way hash function like SHA-512 and storing both the password hash and corresponding unique salt for every user. Though by doing this you won’t be able to retrieve lost passwords and will have to reset them but the limitation is worth the tradeoff for a more secure password storage system.
I would recommend using a cryptographically-strong random value as salt. Using the username or any other user-controlled value would reduce cross-system security, as a user who had the same username and password on multiple systems which use the same password hashing algorithm would end up with the same password hash on each of those systems. Also common usernames like “admin” , “root” would make construction of rainbow tables targeting users with those common names much easier and more effective. Hence use a salt with high entropy and remember that even if user does not exist, the computation time should be equal to the one needed for a legitimate user, therefore, use a dummy salt to check the validity of password in case corresponding userId is not available.
Also consider adding time delay between each sign-in attempts, a 4-5 sec delay between each attempt is short enough to be not noticeable for user but is like an eternity for a cracker trying bruteforce attack. Here is a nice implementation for creating secure password hashes and authenticating users.
Hope it helps