The passhash itself is not stored as-is in the database, it is salted.
Table: Account [username, salt, saltedpasshash]
saltedpasshash = hash(hash(salt)+"::"+hash(passhash));
passhash is generated clientside, using hasher that takes ~1s
So server has salt
, and needs to verify submitted value of hash(passhash+"::"+hash(challenge))
? That doesn't seem possible unless the hash is open to being extended in both directions.
I forgot to add that the server sending the salt to the client is part of the hash challenge.
Both parties can calculate the shared secret (saltedpasshash) and therefore the answer to the hash challenge.
A MITM attack would be successful if the passhash is intercepted during registration and the salt is intercepted during the hash challenge. That's why registration has to be done over a secured channel, while there is no such need for the hash challenge, nor for any further communication using nonce-based access tokens.