Zróbmy notatki do poprzednich odpowiedzi.
Po pierwsze, prawdopodobnie nie jest najlepszym pomysłem używanie algorytmów mieszania po stronie klienta. Jeśli twoje hasło jest solone po stronie serwera, nie będziesz mógł porównać hashów (przynajmniej nie, jeśli nie przechowujesz hasha klienta w bazie danych w jednej z warstw haszujących z hasła, które jest takie samo lub gorzej). I nie chcesz implementować algorytmu haszującego używanego przez bazę danych po stronie klienta, byłoby głupie.
Po drugie, handel kluczami kryptograficznymi też nie jest idealny. MITM mógłby teoretycznie (biorąc pod uwagę, że ma zainstalowany certyfikat główny na kliencie) zmienić klucze kryptograficzne i zmienić je własnymi kluczami:
Oryginalne połączenie (nie biorąc pod uwagę tls) z teoretycznego serwera, który wymienia klucze:
Klucze publiczne żądań klienta> serwer przechowuje klucze prywatne, generuje klucze publiczne dla klienta> serwer wysyła klucze publiczne do klienta
Teraz w teoretycznym atracie MITM:
Klucze publiczne żądań klienta> MITM generuje fałszywe klucze prywatne > Serwer przechowuje klucze prywatne, generuje klucze publiczne dla klienta> MITM otrzymuje klucze publiczne z oryginalnego serwera, teraz możemy wysłać nasze fałszywe klucze publiczne do klienta i ilekroć żądanie przychodzi od klienta, odszyfrujemy dane klienta fałszywymi kluczami, zmienimy ładunek (lub przeczytamy go) i zaszyfrujemy oryginalnymi kluczami publicznymi > MITM wysyła fałszywe klucze publiczne do klienta.
O to właśnie chodzi w posiadaniu zaufanego certyfikatu CA w TLS i tak otrzymujesz komunikat z przeglądarki z ostrzeżeniem, jeśli certyfikat nie jest ważny.
W odpowiedzi na OP: moim skromnym zdaniem nie możesz tego zrobić, bo wcześniej czy później ktoś będzie chciał zaatakować użytkownika z Twojego serwisu i będzie próbował złamać Twój protokół.
Możesz jednak zaimplementować 2FA, aby zapobiec próbom logowania się przy użyciu tego samego hasła. Uważaj jednak na ataki powtórkowe.
Nie jestem świetny w kryptografii, popraw mnie, jeśli się mylę.