Vamos fazer algumas anotações sobre as respostas anteriores.
Primeiro, provavelmente não é a melhor ideia usar algoritmos de hash no lado do cliente. Se sua senha for salted no lado do servidor, você não será capaz de comparar hashes (pelo menos não se você não armazenar o hash do cliente no banco de dados em uma das camadas de hash da senha, que é a mesma ou pior). E você não quer implementar o algoritmo de hash usado pelo banco de dados no lado do cliente, seria bobagem.
Em segundo lugar, a troca de chaves criptográficas também não é ideal. O MITM poderia teoricamente (considerando que ele tem um certificado raiz instalado no cliente) alterar as chaves criptográficas e alterar com suas próprias chaves:
Conexão original (sem considerar tls) de um servidor teórico que troca chaves:
Cliente solicita chaves públicas> servidor mantém as chaves privadas, gere chaves públicas para cliente> servidor envia chaves públicas para cliente
Agora, em uma abordagem teórica do MITM:
Cliente solicita chaves públicas> MITM gera chaves privadas falsas > Servidor mantém as chaves privadas, gera chaves públicas para o cliente> MITM recebe as chaves públicas do servidor original, agora, estamos livres para enviar nossas chaves públicas falsas para o cliente, e sempre que uma solicitação vier do cliente, iremos descriptografar os dados do cliente com as chaves falsas, alterar a carga útil (ou lê-la) e criptografar com as chaves públicas originais > MITM envia chaves públicas falsas para o cliente.
Esse é o ponto de ter um certificado de CA confiável em TLS e é assim que você recebe uma mensagem do navegador avisando se o certificado não é válido.
Em resposta ao OP: na minha humilde opinião você não pode fazer isso, porque mais cedo ou mais tarde alguém vai querer atacar um usuário do seu serviço e vai tentar quebrar o seu protocolo.
O que você pode fazer, no entanto, é implementar 2FA para evitar que as pessoas tentem fazer login com a mesma senha. Alerta para ataques de repetição, no entanto.
Não sou muito bom com criptografia, corrija-me se estiver errado.