I'm not entirely certain what you are saying here. If you mean that the client sends the password and the server rebuilds the hash on it's side, that defeats a portion of the security.
Part of the reason I (in a C++ app) did it this way was specifically so the password was never sent on the wire and was immediately zero'd in memory after sending.
The problem with such a protocol is that the hash of the "password" effectively is the password
. That is, the server requires the client knows H(password + salt) to login (call this the "pass token"). While the password is not sent over the wire, the pass token is. If there was a flaw in the cryptography such that I can view the data on the wire, then I can see and replay the pass token to gain access. Note I do not need to brute force the pass token to do this!
Ok, perhaps I'm overkilling the issue in my code since I exchange public keys, generate stream cypher keys on both sides, exchange those under the public keys, encrypt the stream from that point on yet "STILL" use the public keys for encoding username and the replied hash even in the encrypted stream. Security overkill or useful paranoia?
Security is a complex thing. Sometimes trying too hard - e.g. encrypting too much - can result in insecurity. Sometimes adding encryption doesn't make a significant change to the overall security of the protocol. I would be wary of throwing the cryptographic kitchen sink at the problem, in the hopes of improving security. Instead, start with the list of things you want to prevent (packet sniffing passwords, man in the middle, dictionary attacks/brute forcing the password database, etc...), and design1
a protocol that is immune to these things.
For example, unless you have some out-of-bounds authentication mechanism you didn't mention, the protocol you describe there is vulnerable to MITM. This is exactly the kind of flaw that I was referring to earlier - something that allows a malicious user to obtain the pass token.
Sure, this doesn't directly expose the actual password the user typed (a noble goal). It is also much harder to do a MITM attack than a passive attack. So you've gained some security, but perhaps not as much as you hoped.
It is wise to follow best practise here. The best practise in this case is for the client to send the username/password over HTTPS, and for the server to lookup a salt, compute an expensive hash2
of the salt and password, and compare that to the stored value in the database. 1. I say design, but this has been done before. Borrow heavily from proven protocols, rather than try to make your own.
2. SHA256 etc are called "secure" hashes, but they designed to be fast to compute digital signatures on large amounts of data. This unfortunately works against the design goals of salting (preventing brute force of a small piece of data). Different hash functions, such as bcrypt(), can offer better resistance to brute force attacks. See this article for a detailed description.