Autentificando a un usuario verificando una firma

1

Fondo

Estoy configurando una API que se utilizará principalmente a través de HTTPS (solo las llamadas que no necesiten seguridad alguna, por lo tanto, están disponibles a través de HTTP). Algunos aspectos de la misma deben ser accedidos solo por usuarios autenticados. Para permitir esto sin usar contraseñas, cada usuario posee uno o más pares de llaves RSA. La clave pública se mantiene en el servidor API.

Cuando el usuario desea autenticarse, firma la marca de hora actual con su clave privada y la envía, la marca de hora y una identificación de qué par de llaves se usó en el servidor.

El servidor verifica que el mensaje (la marca de tiempo) fue firmado por un usuario con la clave correspondiente.

El servidor verifica que la marca de tiempo no ha superado una cierta cantidad de tiempo y devuelve un token JWT firmado con la clave privada del servidor que se usará más adelante para autenticar al usuario.

Preocupaciones

La marca de tiempo (que actúa como un nounce (?) y una forma de restringir el acceso de acuerdo con el tiempo) no debe enviarse junto con la solicitud de autenticación al servidor, ya que, al saber qué mensaje se firmó, la clave podría diseñarse a la inversa.

Un usuario no cauteloso podría perder una clave firmada que prácticamente sería tan malo como perder una contraseña, si no peor.

Pregunta

¿Es incorrecto proporcionar qué "nonce" se firmó junto con la solicitud o si el servidor ya "sabe" (a través de algún intercambio anterior)?

¿Usar la marca de tiempo como un mensaje al crear los compendios falsos de la derrota de la firma? Es decir. ¿Es suficiente hacer que el compendio quede inutilizable después del tiempo vencido, ya que el mensaje no se puede modificar sin pasar una verificación?

    
pregunta Alex 18.01.2016 - 17:26
fuente

1 respuesta

1

No me queda claro exactamente por qué está implementando un mecanismo de autenticación tan complejo. Las soluciones de autenticación propias son muy difíciles de corregir. Así que lo primero que pienso es intentar guiarte hacia mecanismos más estándar.

En resumen, mi recomendación es usar el nombre de usuario / contraseña para la autenticación. Si tiene una buena razón para no hacerlo, use la autenticación mutua SSL. Y si tiene una buena razón para no hacerlo, use el método sugerido para cambiar la marca de tiempo a una fuente generada del lado del servidor.

Los detalles siguen ...

Opción 1: simplemente use el nombre de usuario / contraseña para la autenticación. No menciona por qué no está eligiendo esta ruta más común. ¿Quizás esperas un mayor grado de seguridad?

Opción 2: use autenticación mutua TLS / SSL . Esto es un hecho probado. Estándar compatible con casi todos los navegadores web y la biblioteca TLS. En la autenticación mutua, el cliente tiene una clave privada y un certificado X.509, similar al servidor. Cuando se inicia la conexión SSL, utiliza no solo el certificado del servidor, sino también el cliente. Ambos lados de la comunicación pueden confirmar la parte con la que se están comunicando. A diferencia del certificado del servidor, el certificado del cliente no necesita estar firmado por una autoridad de certificación. Esto significa que podría ser un certificado autofirmado o creado por su propia autoridad de certificación. Lo único que importa es que el servidor puede validar que es el certificado correcto para un usuario específico. Mi preferencia es simplemente almacenar el certificado (realmente la huella digital del certificado) en la base de datos del usuario. Esto permite una fácil revocación ya que solo significa eliminar el certificado revocado de la base de datos.

Según la comprensión limitada que tengo de su proyecto, no veo ninguna ventaja para su solución propuesta sobre SSL de autenticación mutua. Está recreando partes del protocolo de autenticación mutua en lugar de utilizar una solución establecida.

Opción 3: su solución de cosecha propia. No veo ningún problema al pasar el nonce en el mismo mensaje que la firma. Como esto se realiza a través de SSL, solo el cliente y el servidor podrían ver esta información. Por lo tanto, no importa si el servidor obtiene el nonce en el mensaje o "sabe" el nonce de una parte anterior de la conversación. De cualquier manera, el servidor tiene tanto el nonce como su firma y nadie más debería tener acceso a esta información.

En cuanto a derrotar un ataque de repetición (lo que supongo que entiendes por "compendios deshonestos"), estoy No estoy entusiasmado con el uso de un nonce generado por el lado del cliente. Creo que es más seguro hacer que el servidor pase el nonce al cliente y luego dejar que el cliente firme esos datos. Esto requiere una ronda adicional de comunicación, pero como estamos discutiendo conversaciones de larga duración en este escenario, creo que esto debería estar bien. Una vez que pase a usar un nonce elegido del lado del servidor, solo puede usar un número aleatorio seguro criptográficamente como nonce y almacén Este nonce en el servidor. El servidor puede entonces manejar la vida útil del nonce. Además, no soy un gran fanático del uso de sellos de tiempo que abarcan computadoras, ya que, incluso en 2016, la sincronización de reloj entre el servidor y el cliente puede ser una molestia.

    
respondido por el Neil Smithline 20.01.2016 - 00:26
fuente

Lea otras preguntas en las etiquetas