Stored on server: x = SHA256("mypassword")
Server challenge to client: send a secure random nonce
Client sends: c = HMACSHA256(nonce, SHA256("mypassword"))
Server verifies: c == HMACSHA256(nonce, x)
In some implementations, the server challenge and 'c' are encrypted using 'x' or some derivation that both sides can create. In addition, salts can remove the sensitivity of the stored 'x' values (https://en.wikipedia.org/wiki/Salted_Challenge_Response_Auth...)