Antes de nada, quiero mencionar que absolutamente NO quiero implementar mi propio criptografía de ninguna manera. Estaba pensando en este tema y después de algunas investigaciones no estaba encontrando una buena solución.
Espero que haya una solución conocida para este problema que simplemente no puedo encontrar.
Suponiendo que hay las tres partes siguientes:
- cliente : asume un teléfono inteligente
- uC : un microcontrolador conectado a la red con un canal inseguro adicional para el cliente
- servidor : algunos servidores backend witch tienen una base de datos y realizan la autenticación normal del servicio web tanto para el cliente como para la unidad de usuario
¿Cómo se lograría una autenticación del cliente contra el dispositivo de uC con una contraseña de un solo uso según los siguientes supuestos?
- El cliente no debe poder autenticarse antes de que el servidor haya dado su "OK". Supongamos algún proceso de reserva / compra y la unidad de control realiza la acción para permitir el acceso
- Los secretos se pueden compartir entre el servidor < - > cliente y entre servidor < - > uC
- El canal entre el cliente y el dispositivo de uC se debe asumir como inseguro
- Un usuario puede tener varios clientes que todos deberían poder autenticarse
- El dispositivo uC es solo uno de muchos en el 'campo', por lo que el cliente debería poder autenticarse contra cualquiera de ellos
- El cliente y el servidor se están comunicando a través de una API REST
- El dispositivo uC tiene, obviamente, capacidad de almacenamiento / almacenamiento limitada, pero también utiliza una API REST para comunicarse con el servidor
- Todas las comunicaciones API se realizan a través de TLS
¿Sería factible el siguiente MSC? Mi idea era básicamente utilizar una cadena hash para crear la OTP. Pero como el cliente no debe saber el secreto para crear el hash, el servidor realiza la generación de la OTP.
+---------+ +---------+ +-----+
| client | | server | | uC |
+---------+ +---------+ +-----+
| | | ----------------\
| | |-| stores h^n(p) |
| | | | and n=1000 |
| | | |---------------|
| | ----------\ |
| |-| knows p | |
| | | and n | |
| | |---------| |
| | |
| request access | |
|---------------------->| |
| | ------------------\ |
| |-| check if access | |
| | | may be granted | |
| | |-----------------| |
| | |
| OTP = h^(n-1)(p) | |
|<----------------------| |
| | |
| OTP | |
|--------------------------------------------------------->|
| | | -----------------\
| | |-| grant access |
| | | | store OTP, n-- |
| | | |----------------|
| | |
| | access granted |
| | if n==0: create new h^1000(p) |
| |<---------------------------------|
| | ----------------------\ |
| |-| save granted access | |
| | | n-- | |
| | |---------------------| |
| | |
| | OK, h^1000(q) if needed |
| |--------------------------------->|
| | |
EDIT : Pensando en ello durante otros cinco minutos, me di cuenta de que esta no sería una buena manera de resolver esto, ya que el servidor básicamente almacena el secreto y el índice del hash. cadena. Entonces, en caso de una violación de datos, se conocerán las PTO para los próximos n ensayos.
¿Podría solucionarse esto almacenando solo el índice de la cadena de hash en el dispositivo uC y comunicándolo solo una vez al servidor? Por ejemplo, si el cliente consulta a la unidad uC por su índice actual antes de solicitar acceso desde el servidor.