I wonder if you've encountered the SRP ("Secure Remote Password") protocol?
It's a particular challenge-response protocol whose details look like a modified version of Diffie-Hellman key exchange. The key feature is that the information the server needs in order to verify the password is not sufficient to perform the client's side of the exchange.
In other words, it gets both the advantages of challenge-response and clear passwords. On the one hand, the data sent by client to server during a verification isn't enough to base further verifications on, so it defends against MITM and replay attacks. And yet it also has the advantage that stealing a password file entry from the server doesn't confer the ability to conduct the client side of the exchange – so your password file isn't an ultra-high-value target either.
You may have encountered this and decided it's not for you – I certainly wouldn't be surprised if it turned out that it was too slow to be practical in client-side Javascript. But you don't mention it here as an option that was considered, so I thought I'd just check.
no subject
It's a particular challenge-response protocol whose details look like a modified version of Diffie-Hellman key exchange. The key feature is that the information the server needs in order to verify the password is not sufficient to perform the client's side of the exchange.
In other words, it gets both the advantages of challenge-response and clear passwords. On the one hand, the data sent by client to server during a verification isn't enough to base further verifications on, so it defends against MITM and replay attacks. And yet it also has the advantage that stealing a password file entry from the server doesn't confer the ability to conduct the client side of the exchange – so your password file isn't an ultra-high-value target either.
You may have encountered this and decided it's not for you – I certainly wouldn't be surprised if it turned out that it was too slow to be practical in client-side Javascript. But you don't mention it here as an option that was considered, so I thought I'd just check.