Si su proveedor de alojamiento web lo permite, o tendrá que tratar con datos confidenciales, utilice HTTPS, punto. (A menudo es requerido por la ley afaik).
De lo contrario, si desea hacer algo a través de HTTP. Yo haría algo como esto.
- El servidor incrusta su clave pública en la página de inicio de sesión.
- El cliente completa el formulario de inicio de sesión y hace clic en enviar.
- Una solicitud AJAX obtiene la marca de tiempo actual del servidor.
- La secuencia de comandos del lado del cliente concatena las credenciales, la marca de tiempo y una sal (hash de datos analógicos, por ejemplo, movimientos del mouse, eventos de pulsación de tecla), la cifra utilizando la clave pública.
- Envía el hash resultante.
- El servidor descifra el hash
- Comprueba si la marca de tiempo es lo suficientemente reciente (solo permite una ventana corta de 5 a 10 segundos). Rechaza el inicio de sesión si la marca de tiempo es demasiado antigua.
- Almacena el hachís durante 20 segundos. Rechaza el mismo hash para iniciar sesión durante este intervalo.
- Autentica al usuario.
De esta manera, la contraseña está protegida y no se puede reproducir el mismo hash de autenticación.
Acerca de la seguridad del token de sesión. Eso es un poco más difícil. Pero es posible hacer que la reutilización de un token de sesión robado sea un poco más difícil.
- El servidor establece una cookie de sesión adicional que contiene una cadena aleatoria.
- El navegador devuelve esta cookie en la siguiente solicitud.
- El servidor verifica el valor de la cookie, si es diferente, destruye la sesión; de lo contrario, todo está bien.
- El servidor vuelve a configurar la cookie con un texto diferente.
Entonces, si el token de sesión fue robado y otra persona envía una solicitud, en la próxima solicitud del usuario original, la sesión se destruirá. Entonces, si el usuario navega activamente por el sitio, haciendo clic en los enlaces con frecuencia, el ladrón no llegará muy lejos con el token robado. Este esquema se puede fortalecer al requerir otra autenticación para las operaciones sensibles (como la eliminación de la cuenta).
EDITAR: tenga en cuenta que esto no evita los ataques MITM si el atacante configura su propia página con una clave pública diferente y envía solicitudes de proxy al servidor. Para protegerse contra esto, la clave pública debe estar anclada en el almacenamiento local del navegador o dentro de la aplicación para detectar este tipo de trucos.
Acerca de la implementación: RSA es probablemente el algoritmo más conocido, pero es bastante lento para claves largas. No sé qué tan rápida sería una implementación de PHP o Javascript. Pero probablemente haya algoritmos más rápidos.