Disclaimer: I'm no expert in cryptography so this answer come from my limited understanding of the protocol.
Let's look at the protocol
SaltedPassword := Hi(Normalize(password), salt, i)
ClientKey := HMAC(SaltedPassword, "Client Key")
StoredKey := H(ClientKey)
AuthMessage := client-first-message-bare + "," +
server-first-message + "," +
ClientSignature := HMAC(StoredKey, AuthMessage)
ClientProof := ClientKey XOR ClientSignature
ServerKey := HMAC(SaltedPassword, "Server Key")
ServerSignature := HMAC(ServerKey, AuthMessage)
Who know what at the start?
- The server knows : salt, i, StoredKey, ServerKey
- The client knows : password
- Both parties know the AuthMessage as part of the exchange
You are right that only the SaltedPassword is required to compute everything but the problem is that no one stores that SaltedPassword. Also, if you want to simply impersonnate the client, you only need the ClientKey to fool the server.
The idea behind SCRAM --> A failure?
The secure authentication mechanism most widely deployed and used by
Internet application protocols is the transmission of clear-text
passwords over a channel protected by Transport Layer Security (TLS).
There are some significant security concerns with that mechanism,
which could be addressed by the use of a challenge response
authentication mechanism protected by TLS.
Still, it doesn't seem to explain how it will protect the password from the server. You have to understand that even if you use some kind of fancy challenge response mechanism to "never" send the password over the wire, that when you enter the password on the browser page, that is served by the server, the script in the page could decide to record your password even if it tells you that it doesn't.
The main advantage, that I see, of a challenge-response mechanism for the users is that they would be able to reuse the same password everywhere. But, since the user really cannot trust the page where it enters his password, he cannot reuse his password.
Then, the next big advantage that I could think of is that in a challenge-response mechanism the password usually isn't stored on the server. So, even if an attacker stole a copy of the server, he cannot try to de-hash the password. Again, it's a big fail since the server has a copy of the StoredPassword, the salt and the iteration count. He has all he needs to try to crack your password via dictionary or bruteforce attack.
At some point, I have to wonder, why not just give the password to the server? The only protection that it adds is that if TLS is broken (but the attacker can only listen), the attacker still has to brute-force your password in order to gain access.