Autenticación HTTP con bcrypt hecho correctamente

2

Tengo una aplicación de Android que se conecta a un servidor a través de HTTP (note la ausencia de S, también Android significa Java, por lo que no se podrá acceder al código en mi aplicación).

Quiero almacenar la contraseña de forma segura en mi base de datos, así que quise usar bcrypt (con contraseña y salt)

Mi problema es el siguiente: ya que estoy en HTTP, no quiero enviar la contraseña simple a mi servidor.

Ya que estoy en el dispositivo móvil y el 3G es muy lento, no quiero enviar el salt al teléfono primero para que pueda enviar la contraseña ya escrita al servidor. (dos consultas en lugar de una)

¿Hay alguna forma de hacerlo funcionar de otra manera que no sea usar el inicio de sesión + una cadena fija como una sal?

¡Gracias!

    
pregunta Taiko 23.07.2014 - 12:36
fuente

2 respuestas

2

Desea utilizar bcrypt para el almacenamiento en el lado del servidor: eso es bueno. Debe recordar por qué que lo hace: es porque teme que el área de almacenamiento del servidor pueda ser saqueada de alguna manera, y desea una capa adicional de protección. El punto de bcrypt (o cualquier otro función de hashing de contraseñas ) es hacer que ataques de diccionario sea más costoso: hay un salt (para evitar ataques paralelos en muchas contraseñas con hash y precomputaciones), y hay muchas iteraciones (para hacer que cada suposición sea costosa).

Por lo tanto, desea maximizar el número de iteraciones. Esto implica que el hashing se debe realizar en una computadora rápida . Un teléfono inteligente con código Java no es rápido (una versión bastante reciente de Android incluye una máquina virtual Java con un compilador JIT lo que ofrecerá una velocidad no demasiado patética, pero el resultado aún no será competitivo con las capacidades del servidor). Por lo tanto, realmente desea que bcrypt suceda en el lado del servidor. Incluso si obtener la sal del servidor fuera aceptable (desde el punto de vista de la latencia de la red), la falta de rendimiento de la CPU en el lado del cliente sería debilitante.

Por lo tanto, su problema realmente es sobre cómo transferir una información muy sensible (la contraseña) desde el teléfono inteligente al servidor, asegurándose de que no sea interceptada mientras está en tránsito. Como una aplicación no puede contener secretos (porque la ingeniería inversa funciona, y eso no es exclusivo de Java), tendrá que usar criptografía asimétrica , con un par de claves pública / privada, de modo que el servidor posee la clave privada, y el cliente puede asegurarse de que usa la clave pública derecha (y no una clave falsa controlada por un atacante) ). En ese momento, estás bastante cerca de SSL.

Usar HTTPS sería el método más simple para lograr lo que buscas; en particular porque el teléfono ya incluye todo el código necesario.

Se podría argumentar que HTTPS implica demasiados viajes de ida y vuelta a la red. Conceptualmente, es factible hacerlo mejor cuando lo que quiere es una transmisión unidireccional de algunos datos secretos al servidor; en ese caso, puede imitar el modelo de correo electrónico, que luego apunta a OpenPGP . Puede cifrar asimétricamente la contraseña para enviarla, utilizando la clave pública PGP del servidor conocido (codificada en la aplicación; eso no es un problema, es una clave pública ) y enviar el resultado como un solo HTTP. solicitud. Esto minimiza el tráfico de la red, mientras sigue confiando en un formato de cifrado que ha sobrevivido a cierta cantidad de revisión externa. Una búsqueda de Google en la "biblioteca openpgp de Android" proporciona algunos indicadores útiles para la implementación real.

    
respondido por el Thomas Pornin 23.07.2014 - 14:45
fuente
0

Lo que está proponiendo sigue siendo inseguro: dado que la sal es siempre la misma para una cuenta dada, un atacante que escucha el tráfico puede simplemente registrar el valor devuelto por su cliente y reutilizarlo después (esto es llamado "< a href="http://en.wikipedia.org/wiki/Pass_the_hash"> pasando el hash ").

Hay formas de ayudar a mitigar ese problema, pero todos terminan con el mismo problema al final: puede asegurar el inicio de sesión, pero todo lo demás (incluido el mecanismo que utilice para mantener el estado de la sesión del servidor) sigue siendo inseguro. y terminas con un modelo de seguridad completamente roto.

Por favor, no intente hacerlo usted mismo: su problema es muy antiguo y tiene una solución fácil de implementar, fácil de implementar, ampliamente compatible y económica: use HTTPS.

    
respondido por el Stephane 23.07.2014 - 14:33
fuente

Lea otras preguntas en las etiquetas