Anteriormente hice una pregunta relacionada, pero esta vez quiero hacer una versión más amplia:
Para simplificar las cosas, digamos que he desarrollado una aplicación que permite a los usuarios enviar mensajes en una sala de chat y entre ellos (similar a IRC). La naturaleza del mensaje no requiere demasiado secreto, nunca se comparte nada sensible.
Desarrollo un servidor de código abierto y un cliente de código abierto para la aplicación. Los usuarios configurarán sus propios servidores, simplemente proporciono el servidor y los programas cliente.
Quiero que los usuarios tengan cuentas en cada servidor. Lo ideal es que el cliente inicie sesión con un nombre de usuario y una contraseña.
Puedo asumir que el cliente no robará la información de la cuenta porque el usuario la obtuvo de una fuente confiable. El problema es que no se puede confiar en el servidor porque:
- El propietario de cada servidor puede hacer modificaciones al código de su servidor.
- Pueden ver el contenido de cualquier base de datos.
¿Cómo puedo autenticar a los usuarios?
- sin permitir que el propietario del servidor acceda a la contraseña del usuario
- sin permitir que el propietario del servidor acceda a un precursor de la contraseña de un usuario (todo lo que no sea la contraseña, pero se puede convertir en la contraseña del usuario o se puede usar para iniciar sesión en otro servidor).
- sin depender de una clave precomputada que debe permanecer oculta en el cliente o en el servidor (el código fuente lo revelaría).
- idealmente permitiendo una contraseña Editar: Idealmente, la contraseña y el nombre de usuario serían todo lo necesario para iniciar sesión, por lo que al iniciar sesión en diferentes máquinas, el usuario solo necesitará la contraseña y el nombre de usuario.
Los enfoques que tengo en mente:
-
Respuesta de desafío: envía un desafío, hash con una contraseña y envíala como respuesta. Esto pasa los números de requisito 1 y 3, pero falla el segundo, ya que requiere que el servidor también tenga acceso a la contraseña con hash, que se puede convertir en la contraseña real, o se usa para iniciar sesión en otros servidores (este último es un poco menor, ya que se puede tratar si ocurre). Mi otra pregunta entra en detalles sobre cómo Implementé esta idea para la prueba.
2: Lista blanca del servidor: Esto se siente un poco como hacer trampa, pero cumple con todos los requisitos al "eliminar" el mayor problema, el hecho de que no se puede confiar en el servidor. Si el cliente intenta conectarse a un servidor que no está en la lista blanca, se emitirá una advertencia con una redacción fuerte (o el acceso a los servidores que no están en la lista blanca podría estar completamente bloqueado). Esto tiene el inconveniente de complicar el proceso de creación de nuevos servidores por parte de los usuarios, y me asigna más responsabilidad que simplemente desarrollar la aplicación (tendría que administrar la lista blanca). Tampoco garantiza necesariamente que se pueda confiar en el servidor, ya que incluso si el propietario no es malicioso, no hay garantía de que tengan la seguridad adecuada en sus sistemas.