Другая идея, которая может соответствовать вашим потребностям, - это так называемая аутентификация с нулевым знанием. (Т.е. серверу никогда не нужно знать пароль пользователя в виде простого текста.)
Обычно при установке начального пароля клиент хэширует пароль пользователя N раз (где N - большое число, например 1000), а затем отправляет этот окончательный хэш на сервер вместе с N. Сервер сохраняет хэш и N .
Позже, когда пользователь хочет пройти аутентификацию, сервер сообщает клиенту N-1, и клиент хэширует пароль, который пользователь вводит N-1 раз, и отправляет его на сервер. Сервер делает еще 1 хэш для полученного хеша и (надеюсь) получает сохраненный хеш. Затем сервер сохраняет хэш N-1 и номер N-1.
Каждый раз, когда пользователь аутентифицируется, сервер уменьшает сохраненное N и сохраняет предыдущий хеш.
Когда N становится равным 0, пользователь должен выбрать и установить новый пароль.
Сервер должен убедиться, что он никогда не запрашивает одну и ту же итерацию, в противном случае он уязвим для воспроизведения. Вы не можете реально выполнить это условие со стороны клиента, потому что клиент (особенно браузер) не может надежно отслеживать последний N.