Background
Estoy intentando desarrollar una aplicación web en la que un usuario pueda iniciar sesión con su contraseña 'P' y, al iniciar sesión, puede crear una contraseña maestra 'MP'. MP se puede usar para abrir / cerrar una bóveda (como los administradores de contraseñas) en la que el usuario puede almacenar información confidencial. Al hacer una investigación sobre el tema, he decidido asegurar lo siguiente:
- La contraseña maestra MP nunca se almacena / envía al servidor
- Todo el cifrado / descifrado se realiza en el lado del cliente (en mi caso es el navegador)
Ahora que estoy almacenando la clave MP ′ (definida a continuación) en la memoria, la bóveda se cierra esencialmente cada vez que se actualiza el navegador o el usuario abre el sitio en una nueva pestaña. ¿Cómo puedo mantener la bóveda para que permanezca abierta durante el tiempo que el usuario quiera? La cookie no es una solución, ya que hará que se envíe MP ′ al servidor en cada solicitud; sin embargo, el almacenamiento local HTML5 puede ser una posibilidad
Ahora, si un pirata informático obtiene acceso al almacenamiento local, obtendría un MP ′ y podrá descifrar toda la información confidencial al usarlo. Como solución aquí es en lo que estoy pensando:
- Cuando se abre la bóveda, el cliente solicita una clave aleatoria única 'Rk' desde el servidor
- El servidor genera Rk, lo almacena en la sesión del usuario y lo envía de vuelta al cliente
- El cliente usa Rk para cifrar MP ′ para obtener MP ′ ′
- MP ′ ′ se almacena en el almacenamiento local de HTML5 mientras que Rk se guarda en la memoria
- Cuando sea necesario, el MP ′ ′ se puede descifrar usando Rk y se usa para operaciones posteriores
- Al actualizar el navegador, el cliente vuelve a buscar Rk del servidor (el servidor simplemente devuelve el que ya está almacenado en la sesión)
- Rk ha caducado si el usuario cierra explícitamente la bóveda o finaliza la sesión al cerrar sesión
La pregunta
¿Qué tan segura sería esta solución? ¿Alguna advertencia obvia que me esté perdiendo? ¿Cuál sería el enfoque ideal para solucionarlo?
Notas adicionales
Para su comprensión, aquí hay un breve resumen de cómo planeo satisfacer mis necesidades:
- El usuario crea un nuevo MP
- MP está encriptado con un algoritmo de estiramiento de claves para producir MP ′
- MP ′ se usa como una clave para cifrar un valor conocido V para obtener Vh (obviamente V ≠ MP o MP ′)
- Vh se almacena en el servidor contra el registro del usuario
Vh sirve 2 propósitos:
- Indica que el usuario ya ha creado un MP. Si aún no está allí, puedo pedirle al usuario que cree uno nuevo
- Cuando el usuario ingresa a MP para abrir la bóveda, puedo recuperar Vh del servidor e intentar descifrarlo con MP ′. Si el descifrado es exitoso, asumo que el usuario ingresó el MP correcto
Como puedes imaginar, así es como debería funcionar el resto:
Siempre que el usuario desee almacenar / recuperar información confidencial:
- Se conectan con P y abren su bóveda con MP
- El cliente produce MP ′ como se mencionó anteriormente
- La información confidencial se encripta utilizando MP ′ antes de enviarse y almacenarse en el servidor
- Según la necesidad del usuario, la información confidencial encriptada se recupera del servidor (como está)
- El cliente usa MP ′ para descifrar los datos