I'm developing a software in which I need to transmit sensitive data (passwords) in a server/client configuration using TCP. All data is encrypted using AES (the symmetric key is unique to each exchange and transmitted using PGP/RSA, this part is secure).

I'd like, for added security, to hash the sensitive data before sending it. The passwords are stored in a sql database. Using SHA-256/512 works wonders, but I'd prefer using BCrypt which is rock-solid in case the database is stolen. However since BCrypt requires the plain password to verify matches and since the check is done server-side, this would require me to send the password in plain text (albeit, AES-encrypted). I've also thought of doing around 1000 hashing iterations of the password using sha-256/sha-512 but I'm unsure if it's really the best idea.

What would be the best way to ensure a fully secure transmission, and a fully secure storage of passwords ?

up vote 2 down vote accepted

Without proper transport level security (i.e. a TLS connection) it is not possible to secure an application against man-in-the-middle attackers. Using bcrypt or something else to transfer the password doesn't help the situation. You should have a secure connection between the client and the server, with both encryption and authentication.

Once you have that, there is no problem in sending the password just as is over the secured connection.

Another attack surface is a database compromise, for which the proper solution is to store a bcrypted password instead of a plaintext password in the database.

  • Yes, just using a hash is not enough. I've settled for an RSA (asymmetric) encryption of sensitive data inside the already-AES-encrypted transmission. The password is stored bcrypted into the database and encryption informations are unique to each transmission, rendering replay attacks undoable. – Corentin Brossutti Jan 24 at 12:09

One possibility is to hash the password both on the client and on the server.

  1. The client sends bcrypt(password) to the server.
  2. The server computers bcrypt(bcrypt(password)) and checks the password against the database.

Passwords in the database are thus bcrypted twice. This way, the plaintext passwords are safe against interception and the authentication token is safe against database compromise.

  • How about just using SHA on the server so you don't have to store multiple salts and costs? And this has been covered in the duplicates schroeder linked. – AndrolGenhald Jan 23 at 16:24
  • Edited because of my lack of my forethought...It seems to be a very good solution but as I'm writing this, I'm wondering : isn't then the hash effectively the password ? Wouldn't it be better to not use a hash at all and use another layer of encryption (asymmetric maybe) to transmit the password, and then decrypt it into plain text on server side ? – Corentin Brossutti Jan 23 at 16:44
  • @CorentinBrossutti What are you trying to protect against? The only thing client side hashing (or encryption) can protect against is a passive attacker that can break TLS, hoping that you re-use the same password elsewhere. – AndrolGenhald Jan 23 at 16:54
  • @CorentinBrossutti Actually I'll amend that, since I was thinking in a web context that might not be true in this case. As long as the server can't push code updates to clients it should also protect against an active attacker that hacked the server. – AndrolGenhald Jan 23 at 17:28
  • @AndrolGenhald That was my original idea, to prevent attackers from getting a plain text password. But as I'm thinking about it, another concern is that in our configuration if a hacker was to get the decrypted authenthication packet he could inject code client-side and actually usurp the client he stole data from, hash or not. That's why I am, since I do have an asymmetric encryption currently setup, thinking about just encrypting the password separetely. Since the key pairs are unique to each exchange, this would prevent a hacker from doing the above. – Corentin Brossutti Jan 23 at 17:44

You could try sending the salt to the client, that would then use that to BCrypt the password. Or have the client BCrypt the password.

Then, the server would run a BCrypt of the password and verify it matches.

APPARENTLY this is more secure -- except it is not. Because if the attack you're defending against - capture of the transiting secret - succeeded, the attacker would now be in possession of BCrypt(pwd) -- and, with that, he could gain access and impersonate a legitimate client. The system no longer requires knowledge of the password, only of its bcrypt hash. You are now exposed to a replay attack.

To be able to change the salt, and defend against replay attacks after a successful capture, you would need to store the plaintext password.

What you can do then is: - memorize the bcrypted password with salt S1 on the server, each password has its own salt - send the client a challenge containing S1 and SX (generated at random each time); this requires the user having already been sent to the server. An unknown user receives a salt built by hashing a secret with the username. - the client has the plaintext password and sends you Bcrypt(SX, Bcrypt(S1, password))

  • you have Bcrypt(S1, password) and are thus unable to reveal the password
  • the wire sees Bcrypt(SX, hash) and is thus unable to reveal the hash
  • you get a CPU-hard bcrypting at each stage.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.