Objetivos
Estoy implementando un sistema basado en la web que tiene los siguientes objetivos:
-
Los usuarios pueden almacenar secretos (puede ser una contraseña o un archivo completo) en el servidor.
-
El servidor no tiene conocimiento de las claves para el descifrado. De modo que si el servidor está comprometido, el atacante no podría descifrar los secretos.
-
Los secretos se pueden compartir entre los usuarios.
Diseño
La principal amenaza que me preocupa a los efectos de esta pregunta es el compromiso del servidor. Quiero asegurarme de que si un atacante obtiene acceso al servidor o la base de datos (fuera de línea o en línea), no se exponen secretos. Entiendo que hay otras amenazas, como una cuenta de usuario comprometida. Se establecerán otros dispositivos de seguridad para protegerse contra eso.
Decidí que es más seguro que el servidor nunca vea un secreto de texto simple o el material clave. Por lo tanto, todo el cifrado se realiza del lado del cliente. Estoy usando asmCrypto .
-
HTTPS se utiliza para todas las comunicaciones cliente / servidor. Los usuarios requieren cuentas, ya existe un sistema de autenticación.
-
Los usuarios generan un par de claves RSA personales (2048 bits, e = 65537). La clave privada se encripta con AES-GCM usando una clave generada por PBKDF2 basada en la frase de contraseña proporcionada por el usuario. El servidor genera el nonce AES para garantizar la exclusividad. La clave pública del usuario y la clave privada encriptada se envían al servidor para ser almacenados.
-
Cuando un usuario guarda un secreto, genera una clave única aleatoria (K) para ese secreto. Cifran el secreto con AES-GCM usando K y un objeto proporcionado por el servidor. Luego cifran K usando su propia clave pública y el relleno OAEP. Además, pueden cifrar K con la clave pública de otro usuario. Las copias cifradas de K se envían al servidor.
-
Para leer el secreto (posiblemente de otra computadora), un usuario debe recuperar su clave privada cifrada del servidor. Descifran su clave privada del lado del cliente al proporcionar una frase de contraseña, que se alimenta a PBKDF2 para generar la clave AES. Una vez que se descifra su clave privada RSA, pueden descifrar la clave secreta (K) y, posteriormente, el secreto.
Preguntas
Sé que hay muchos escollos y posibles errores con el cifrado. He leído mucho para tratar de comprender la mejor manera de usar estos algoritmos (por ejemplo, el nonce único para AES-GCM, el valor de e para las claves RSA y la importancia de usar el relleno correcto). Sin embargo, no estoy completamente seguro de que este sea un diseño sensato.
¿Qué defectos ves en este diseño?
¿Son correctas las opciones de algoritmos y parámetros?
¿Hay alguna manera de juzgar la calidad de la biblioteca asmCrypto?
¿Me falta una solución más simple y obvia?