¿Cómo garantizar la sincronización del contador entre el cliente y el servidor para el contador en la implementación de contraseña única basada en hmac?

2

Este es un clon de una pregunta que publiqué en Stack Exchange. Pensé que podría llamar la atención de algunas personas diferentes que podrían ayudar aquí.

Estamos intentando implementar un protocolo de contraseña de una sola vez basado en hmac para usar usuarios que se autentiquen en nuestra API.

La idea es cifrar un identificador único para el usuario (uid) contra una clave privada y un contador incremental. Luego incremente el contador para la siguiente llamada.

encrypt(uid, private_key, counter)
# now increment the counter for the next call

Luego, en el lado del servidor, descifre usando la clave privada y el contador para obtener el identificador de usuario (uid).

decrypt(encrpyted_string, private_key, counter)
# now increment the counter for the next received request

Esto funciona bien. Cada llamada es completamente única (una vez) debido al contador.

Sin embargo, ¿cómo manejaríamos la sincronización del contador? ¿Qué sucede si el cliente genera una solicitud, incrementa el contador para la siguiente llamada y envía la solicitud, pero el servidor está fuera de línea y nunca recibe la solicitud, o si hay un problema de conectividad a Internet y la solicitud nunca se recibe? Ahora el servidor y el cliente no está sincronizado con los contadores del otro.

¿Es este un caso de "debe saber si se ha enviado una solicitud"? Es decir. podríamos agregar un encabezado de respuesta desde el servidor para indicar si el contador se ha incrementado y solo si lo hace, también incrementamos el contador en la aplicación ... pero lo mismo podría decirse al revés: podríamos enviar un La solicitud, el servidor lo recibe, incrementa su propio contador y envía una respuesta, pero la conexión a Internet se ha interrumpido mientras el servidor procesaba su solicitud y la aplicación nunca recibe la respuesta, nunca incrementa su contador y, por lo tanto, los dos no están sincronizados. de nuevo.

Gracias por cualquier información que puedas darme.

    
pregunta Thomas Clayson 21.03.2013 - 18:35
fuente

2 respuestas

3

Consulte HOTP , sección E.4 . Esto está razonablemente bien explicado. La esencia de la solución: cuando el contador en el servidor contiene n , el servidor realmente acepta como válidas las contraseñas de un solo uso correspondientes a los valores n , n + 1 , n + 2 ... hasta (digamos) n + 99 . Si lo que el cliente envió coincide con la contraseña de un solo uso para el valor n + 37 , entonces el cliente es aceptado y el nuevo valor del contador en el servidor se establece en n + 38 . El ancho del rango aceptado por el servidor es un compromiso: un rango mayor tolera a los clientes que están muy desincronizados, pero es más costoso en el lado del servidor (más contraseñas potenciales para calcular) y disminuye la seguridad ( ya que, en cualquier momento, las contraseñas distintas se considerarán "aceptables".

    
respondido por el Thomas Pornin 21.03.2013 - 19:19
fuente
2

Por lo general, la solución para esto es a) compararla con los valores que van más adelante para ver si esto ocurrió y aumentar en consecuencia si se descubre que se ha adelantado. (Así es como los tokens basados en el tiempo cuentan para la desviación del reloj.) O b) si los sistemas pueden interactuar, realice un intercambio del valor del contador actual en ambos sistemas. Pueden ponerse de acuerdo en lo que sea el último valor utilizado y usarlo. Vale la pena señalar que sin una limitación de tiempo, sin embargo, la repetición será posible, ya que un sitio de phishing podría solicitar el siguiente código y luego usarlo para hablar con el servidor. Un sistema basado en el tiempo limitaría la ventana de oportunidad para un ataque de este tipo para garantizar que el usuario esté tratando de seguir adelante en ese momento y, por lo tanto, notaría (con suerte) que se rechazó su sesión legítima.

    
respondido por el AJ Henderson 21.03.2013 - 19:11
fuente

Lea otras preguntas en las etiquetas