Desde el punto de vista criptográfico, si un usuario A debe poder hacer algo que otro usuario B no puede (por ejemplo, enviar un mensaje con " A "como nombre del remitente), entonces debe haber algún valor que A sepa pero B no. Ese tipo de valor secreto se denomina clave , aunque existen otras terminologías (por ejemplo, "contraseña" cuando el secreto se almacena en un cerebro humano).
La ocultación de claves dentro del código de la aplicación tiene dos grandes inconvenientes:
- Se pueden recuperar mediante ingeniería inversa.
- No son específicos del usuario.
Sin embargo, en su caso, desea un valor secreto específico del usuario: cada usuario tiene su propia clave, con la que se autentican sus mensajes. Por lo tanto, la clave del usuario no puede ser codificada en el código de la aplicación compilada; sin embargo, puede almacenarse como un archivo en el dispositivo del usuario. La ingeniería inversa no es un problema: mediante la ingeniería inversa de la instalación de su propia aplicación, el usuario puede aprender su propia clave, no la clave de otra persona.
El punto importante aquí: dicha clave autentica al usuario , no al dispositivo . Asegurarse de que un mensaje dado provenga de un dispositivo específico, y enviado por "su aplicación no modificada" y no por otro código, es casi imposible, ya que dicho dispositivo está físicamente en manos del usuario, y no es a prueba de manipulaciones Para obtener este tipo de garantía, necesita un dispositivo que pueda luchar contra su propietario, por ejemplo. una tarjeta inteligente . La facturación de los teléfonos móviles funciona de manera práctica y legal, porque el usuario no puede acceder a su propia tarjeta SIM. No puede tener este modelo con una aplicación que sea solo de software en hardware no blindado (el propio teléfono).
Sin embargo, siempre que desee autenticar usuarios, no dispositivos, entonces una clave específica del usuario está bien.
Luego viene la parte difícil: la autenticación es buena, pero ¿quién la está haciendo?
Si solo quiere que su servidor se asegure de la identidad de A , entonces un secreto compartido entre A y el servidor S puede estar bien. La herramienta criptográfica subyacente sería un MAC . Sin embargo, en ese caso, cuando el usuario A envía un mensaje al usuario B a través de su servidor, el servidor está seguro de que efectivamente habla con A , pero B no sabe nada. Un usuario malvado E , que desea falsificar un mensaje falso que supuestamente proviene de A , puede enviar dicho mensaje directamente a B , sin pasar por su servidor en absoluto!
Una solución, en ese caso, es hacer que la comunicación de S a B se autentique por igual con la tecla B : esta vez, es B quien se asegura de que lo que recibe de S sea de S . Con MAC aplicado en ambas direcciones, para todas las comunicaciones entre el servidor y cualquier usuario, puede tener una red de mensajería razonablemente segura. Por supuesto, S es de confianza : su servidor puede traicionar a todos a voluntad. Pero tal vez esto no sea un problema para ti.
(Para la autenticación de extremo a extremo, sin confiar en un servidor central, tendría que recurrir a la criptografía asimétrica y firmas digitales , y las cosas se vuelven mucho más complejas.)
El almacenamiento de una clave específica del usuario en un archivo en el dispositivo del usuario parece bastante simple. Sin embargo, a veces, los usuarios cambian de dispositivo (por ejemplo, compran un teléfono nuevo o son adictos a Apple que tienen un iPhone y un iPad) y aún desean conservar su identidad . Esto implica que la clave específica del usuario de alguna manera viaja desde un dispositivo al usuario.
El esquema que usted visualiza (almacenar la clave en el propio servidor, con descarga automática después de la autenticación basada en contraseña) es válido. Asegúrate de hacerlo sobre SSL, por supuesto. Puede combinarlo con un mecanismo de almacenamiento en caché: la aplicación descarga la clave cuando aún no la tiene, pero luego la almacena en el dispositivo.