Is there a perpetual 2-factor-authentication scheme that allows temporary password generation? Recall that current forms of two-factor authentication (2FA) rely on:

Something you know, i.e. your password

Something you have, i.e. your one-time password (OTP) generator on a trusted device


The procedure is as follows:

Client sends username (public)
Client sends password (private)
Client sends otp = HashOTP(client_seed, time())
Server looks up salt, salted_password_hash, and seed for username
Server compares HashPW(password, salt) against salted_password_hash
Server compares HashOTP(seed, time()) against otp
Client is authenticated iff all comparisons succeed.

The idea, of course, is that even if all the transmitted information is intercepted by an attacker, the attacker is unable to authenticate because he does not have the client_seed to generate a subsequently valid otp.
So far so good, except that interception of password permanently reduces 2FA to 1FA.
&quot;Permanently&quot; because the user will have no idea his password is compromised, and will therefore have no reason to change it.
So, ironically, not only is otp a &quot;one-time password&quot;, but so is password itself. (!)
(Now, at this point, I'm sure some of you are ready to close the question, thinking, &quot;But TLS should have protected the password during transit, and if the client itself is compromised, then the problem is invalid!&quot;
If you're in that camp, well, realize that's not how the world works. A passive keylogger on the client could be secretly recording everything but the actual stolen credentials are likely to stay unused until a while after, when the user is unlikely to notice it. So it makes sense to render any such keylogger useless if possible.)
Given that the user will reuse password without even knowing that his 2FA is really 1FA, a theft of his device is all that stands between him and his account, and he is likely to think he is safe because he has no idea his password might have been compromised.
How, then, can we address this?
Initially I was thinking that the user could type his password into his trusted OTP generator and generate a single one-time password that will authenticate him without ever having to send his actual password.
But now it seems to me the server would need to know the password itself in order for this approach to work. In other words, it defeats the storing of hashed passwords—i.e., a server-side leak will now reduce all users' 2FA to 1FA, instead of a client-side leak.
Basically, it almost seems that 2FA is fundamentally 'single-use': any attacker with read-only access will reduce 2FA to 1FA, and the client and server can remain indefinitely unaware.
But I don't know if this is really the case.
Can we keep the two-factor nature of 2FA even after a client or server data leak, without otherwise weakening the system's security? How (or why not)?
If you use asymmetric cryptography you can make it work. The trusted device stores a private key and salt the user will type his password and it will get hashed with salt and get encrypted/signed and the result sent to server which has public key and the salted hashed password. The main problem is the trusted device now sends something much larger then the common short tokens used today. Also public key crypto is more computationally expensive, we know how to make the server side cheap but not both sides.
A server breach doesn't expose the private key, a trusted device breach doesn't expose the password and a loss of password doesn't expose the private key.