简体   繁体   中英

Transmit user password for a rest api

I'm designing a REST API and I have some problems in terms of security for authenticating the user. For authentication I don't want the password to be send across the network in plain text.

To bypass this problem I could send a SHA-256 hash of the password (with the username as salt), so the password is never sent in plain text. In my database I will be storing the following hashes: SHA256(password + salt) and I'll compare if both of the hashes match.

The problem with this option is that I'll have a hash computed with a fast hash algorithm and the salt is not random.

In security the best practice is to use a slow signature algorithm, with a random salt (like bcrypt).

The slow algorithm is not a problem, i could use bcrypt on the client side, but for the salt i don't know what to do:

  • Bcrypt need a salt with a defined size so i can't put the username
  • If i'm using a random salt, how the client will know the value of this salt before computing the password's hash?

So i can see 3 options, but none are sastisfying:

  • I send the password in plain text (I'm using SSL) and i store bcrypt in the db => still vulnerable to man in the middle
  • I use SHA256 and send the hash where the salt is the username (still using SSL) => the hash in the db are less secure
  • I use bcrypt and I have a two step process: i ask for the saltfor a given user and then send the hash of this user (still using ssl) => by trying to log in with an other username i can obtain his salt, not awesome

Is anybody has a better solution or some advices?

There a couple of advantages to the approach of hashing on the client side. One of them is the server never gets the real passwords, so if the server is compromised in any way, it still won't get the real password. The other one is, it can lighten the load on the server side if you're planning to use slow hashing.

However, hashing passwords is designed to protect you in case the database is breached and hashes are stolen. This means if someone gets a hold of the hashed passwords, they could still impersonate users by sending the hash. The implication is, even if you hash on the client side, you still need to re-hash on the server.

The other potential downside is that this could alienate part of your userbase that doesn't have JavaScript enabled.


To address your points:

Bcrypt need a salt with a defined size so i can't put the username

Don't use the username as a salt. Salts should be unique, and a username (and derivations thereof) is certainly not unique. By unique I don't mean just unique to the server, but unique everywhere. Use a cryptographic nonce instead.

If i'm using a random salt, how the client will know the value of this salt before computing the password's hash?

Just have the server send the salt (nonce) beforehand. You could do this on the client as well, but the Javascript doesn't have a CSPRNG as far as I know, and you'd still need to send the nonce back to the server.

I send the password in plain text (I'm using SSL) and i store bcrypt in the db => still vulnerable to man in the middle

SSL was designed to prevent man in the middle attacks. Unless it's broken somehow, that's not going to be a problem.

I use SHA256 and send the hash where the salt is the username (still using SSL) => the hash in the db are less secure

Don't use username as a salt. And like I said before, you have to hash on the server side regardless of whether or not you did it on the client side.

I use bcrypt and I have a two step process: i ask for the salt for a given user and then send the hash of this user (still using ssl) => by trying to log in with an other username i can obtain his salt, not awesome

Not awesome indeed.

I think you might be conflating/confusing a few issues here:

  • If you're storing the hash(password + username) on the server, and authentication involves sending hash(password + username), you haven't really achieved anything better than just storing the password on the server. The goal of only storing hashes long-term is that if you have a data breach (ie, an attacker gains access to the database) they still can't produce the correct value to authenticate. But if you're doing a simple comparison, this is still an issue.
  • The correct use of hashing+salting is: (1) Server stores tuples of (Salt, hash(Password + Salt); (2) User sends (claimed Password); (3) Server computes hash(claimed Password + Salt); (4) if hash(claimed Password + Salt) == hash(Password + Salt), then they're authentic. In this way, even if an attacker gets access to the database, they can't produce a claimed password that such that hash(claimed Password + Salt) is valid.
  • Sending a plaintext password via SSL is not "in the clear". Per @NullUserException's comment, unless the attacker has broken SSL. Only the server will be able to obtain the value of the password (assuming the server's public key is valid, which is a whole 'nother story).

Hope this helps!

  1. Make the salt constant, let's say make it a hash of the username. So hash_val = HASH(HASH('username') + 'password') is stored server-side.
  2. For authentication your server sends a single-use random value, ie: nonce = HASH(RAND())
  3. Your client computes the following based on the input credentials client_hash = HASH( nonce + HASH(HASH('username') + 'password')) and sends it back to the server.
  4. The server perfoms the same operation, compares the resulting hashes, and discards the nonce.

In this way the hash sent over the wire is used only once and you're protected from 'replay' and MITM attacks.

Also, look into something like PBKDF for storing passwords rather than just hashes, it makes both bruteforcing and rainbow tables completely impractical. Here's the PHP implementation I'm using since it's not in PHP yet .

If possible create API Key and secret key (API username/password, obviously unique for each user) to use API. You should give an option in your site interface to activate/de-active the API access as well as option to re-generate the API Key and secret key. Here, on this interface users will see the API/Secret key of the API.

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