A naive developers might store a password in the database directly, which would then be compared directly with the password sent from a client. A more security conscious developer might instead store only the hash of the password in the database, and then compare the hash of the password from the client. But most people use the same few passwords for their accounts. As such, a site that requires an email and password for an account/login may then be given access to every other site for which the user supplied the same email + password.
So what if the client were to create the hash itself? In this case, the hash would be sent to the server, but again it doesn't matter - if I know what hash you use to log in to google.com, the hash will be the same for amazon.com (assuming the same algorithm). So how about appending a string from the server onto the password, then hashing? Example:
- I go to amazon.com, and am asked for my credentials
- With the login page, amazon sends a guid: 'cdfefe81-d466-49a6-acea-140fa52c0901' (this may be associated with the user account, or just have 1 for all of amazon)
- I enter my password, 'safe_password'
- The client append the guid to create 'safe_passwordcdfefe81-d466-49a6-acea-140fa52c0901'
- This is hashed using whatever hashing algorithm is appropriate, and then sent to the server. Inside the server, the hash is re-hashed (with a salt) and compared with the hash in the database to authenticate.
The advantage of this flow allows a user to use the same or similar passwords for multiple servers, and as long as all such clients follow this pattern, no server would ever know the users actual password, even if that server were compromised.
Edit:
To clarify, the goal is to protect the user's password, assuming a server is completely compromised. If I run a site that requires login, by receiving a salted hash from the client (where I provide the salt), even if a malicious user has access to all the data on the server side, they would never be able to find the user's original password, assuming a good hashing algo, which would significantly limit the potential impact to users for a security breach.
Another application would be credit card numbers, which are a lot like passwords. Imagine this scenario: I am responsible for validating credit card numbers at Visa to approve charges. Amazon wants to use my service, as does every other major vendor in the world. So I tell Amazon "I won't authenticate any credit cards from directly from a number. Instead, I'm going to require you send me a hashed version of a string, and since you've registered with us as a vendor, here is a GUID that will be assigned to your account". The string would be something along the lines of <cc#>:<expiration>:<GUID supplied *to Amazon* by Visa>
.
So this whole flow:
- Amazon wants to process CC's, requests GUID from Visa
- Visa generates GUID, sends to Amazon, and associates the GUID with the account
- Amazon sends GUID with credit card input page to buyer
- On client side, after CC info is entered, this information is never sent to Amazon unhashed Instead, the client constructs the string as described above, hashes it, and sends the resulting hash to Amazon.
- Amazon wants to allow for repeat orders, so it stores this hash in their database.
- To authenticate, Amazon uses existing S2S authentication model to prove that they are Amazon.com, and sends the hash from the client, along with the buyer's name, address, etc.
- Visa receives said hash, looks up Amazon's GUID, and finds all cards owned by the specified buyer. For each card of the buyer, Visa re-constructs and re-hashes the card number + exp date + Amazon GUID, and compares the hash with what was received from Amazon.
- Visa finds a match, says Amazon is OK to charge this card, and Amazon sends a confirmation of said charge.
Given this flow, even if I were to gain access to all of Amazon.com databases, servers, hard drives, emails, incoming traffic, etc, I would never know the user's credit card number. The most harm I could possibly inflict would be if I can spoof being an Amazon.com server, I may be able to charge the user on behalf of Amazon.com, but that would presumably then go into Amazon.com's account, so I wouldn't likely benefit from this at all. In an ideal situation, this flow would be part of the SSL logic, such that only site that implement something of this nature receive the lock symbol in client browsers (haven't thought this through entirely, but seems plausible)