Most websites will send the password plain-text over an encrypted connection SSL/HTTPS. Hashing the password client-side can be done, but the advantage is small and often client-side languages (JavaScrypt) are slow so you can calculate less rounds in the same time, what weakens the hash. In every case the server must calculate a hash as well to be safe.
The advantage is small, because if an attacker can do a ManInTheMiddle attack, he can also modify/remove the script (JS) which does the hashing. Only an encrypted connection with SSL/HTTPS can protect against a MITM attack, so you need SSL anyway.
In your case with an app, it looks slightly different. Because the user first has to install your software, there is no need to send a script to the client, so a MITM cannot modify this script. Moreover, the app can calculate the hash relatively fast (if it can run native code) and therefore can do enough rounds on client-side.
This is what i would do:
- For easiness send the password plain-text over an encrypted SSL/HTTPS connection and calculate the slow BCrypt hash server side, as you do now.
- Only if the load on the server grows too heavy, then you can move the calculation of the slow BCrypt hash to the client app. Still use HTTPS to send the hash, and then calculate an additional fast hash (e.g. SHA-256) on the server. This is more complex, because you have to exchange and store the salt separately.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…