简体   繁体   中英

Secure user authentication - Am I doing it right?

I am developing an Asp.NET site for a customer, and want to make sure I am using a secure authentication scheme.

In my user table, I have an authentication hash column that is calculated as sha1(salt + username + password) . The site is being served via HTTPS. To log in, the user submits their name and password via HTTPS. The web server calculates the hash, and compares it to the database stored value to authenticate.

Does this sound reasonably secure? I ran this scheme past a friend of mine, and he said it was vulnerable to nefarious sys-admins. He said I should do the following:

  • Server specifies a unique salt every time the login page is served.
  • Hash the password the unique salt on the client via javascript before submission.
  • Send this hash to authenticate, but not the password.
  • Do some fancy crap that I don't understand to authenticate the hash.

What should I do?

不要重新发明轮子,只需使用.Net Membership即可

Firstly, if users are connecting via HTTPS, then there shouldn't be an issue with sending the password to the server over the network.

Otherwise, ensure that your salt is long and uses decent entropy for randomness. Also ensure that you use SHA-2 rather than SHA-1 since SHA-1 is considered broken .

Does this sound reasonably secure? I ran this scheme past a friend of mine, and he said it was vulnerable to nefarious sys-admins.

It's always a little dangerous to send out a password directly. Even if you're using SSL. If this is what he's referring to then he's kind of right. I wouldn't say it's vulnerable, just not the safest approach.

  • Server specifies a unique salt every time the login page is served.
  • Hash the password the unique salt on the client via javascript before submission.
  • Send this hash to authenticate, but not the password.
  • Do some fancy crap that I don't understand to authenticate the hash.

It sounds like he's suggesting a challenge-response scheme in conjunction with SSL. This is a good approach but let me explain it step by step to be clear.

Upon registration, the password is sent across ssl to the server. This should be the only time the password is sent directly. The server generates a salt and stores the following hash:

hash = sha1(password + salt)

The server should also store the salt.

When the client visits a log in page, the server should generate a record in a table with an ID and a challenge value. The server should then send the ID, the stored salt and the challenge value to the client.

When the client is ready to log in, you should have a javascript function generate a challenge as well as a hash like so:

hash = sha1(sha1(password + server_salt) + server_challenge + client_challenge)

The client should then submit the hash, the server_saltid and the client_challenge values. The server then calculates a hash like so:

hash = sha1(stored_hash + server_challenge + client_challenge)

If the hashes match the user is authenticated, in either case, the challenge record should be deleted.

Read this:
Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes

What have we learned?
...If it's 2007, and rainbow table attacks set you on fire, we learned that you should go back to 1975 and wait 30 years before trying to design a password hashing scheme.
...we should be consulting our friends and neighbors in the security field for help with our password schemes.
...in a password hashing scheme, speed is the enemy. We learned that MD5 was designed for speed. So, we learned that MD5 is the enemy.
...if we want to store passwords securely we have three reasonable options: PHK's MD5 scheme, Provos-Maziere's Bcrypt scheme, and SRP. We learned that the correct choice is Bcrypt.

The key points here:

  • Whatever you do, don't try to build your own authentication code from scratch
  • Bcrypt is your best choice for hashing the password.

If you change the salt with every login page served, how can you compare it to what is in the database that is hashed with a different salt?

Your under SSL so you could send the credentials free text since the line is encrypted already and then apply the rules to salt/hash your password for comparing server side. This way no one knows how you are encrypting your password. Storing the informtion in your client side javascript is just giving that information away.

Other than that, your approach looks correct. I am assuming you need a custom solution and not a built in one for whatever reason.

Your friend is correct in asserting the salt should be unique however he's wrong with regards to handling the salt.

  • Hash the password the unique salt on the client via javascript before submission.

That requires you to either use the same salt for everyone or know who the user is so you can send them their unique salt. The salt should never leave the server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM