He creado una API que permite a los usuarios enviar datos cifrados para que se almacenen en la nube. Para recuperar sus datos, la API requiere que el usuario proporcione solo el ID de objeto MongoDB que se les proporcionó cuando se enviaron inicialmente sus datos, más el hash SHA1 de la contraseña que utilizaron para cifrar los datos. Elegí usar tanto el ID de objeto como el hash de contraseña como una clave única para evitar que los usuarios soliciten datos a través de la API, ya que los distintos ID de objeto no son complejos y fáciles de adivinar.
Ahora he cambiado el método hash de SHA1 a bcrypt porque es más seguro, pero eso ha presentado un problema. Debido a que bcrypt genera una sal diferente cada vez, el hash siempre tiene un significado diferente, ya no puedo usar el hash generado para identificar los datos del usuario en la base de datos, a menos que fuerce a la aplicación a usar la misma sal cada vez que genere un hash bcrypt. Nota: si uso un sal constante, el público lo sabrá ya que el código fuente es de código abierto.
Mi pregunta es, si uso un salt constante con bcrypt para generar hashes de contraseña, ¿esto hace que los hashes sean más fáciles de descifrar que usar SHA1 como lo era originalmente, y si no es así, sigue siendo un enfoque poco práctico para crear hashes de contraseña seguros? ?
Alternativamente, ¿existe un mejor enfoque para especificar una clave única para los datos del usuario en la base de datos sin pedirle más información al usuario?
Editar: Al tratar de mantener la pregunta lo más simple posible, me he dado cuenta de que realmente no he brindado suficiente contexto para explicar por qué elegí el enfoque que tengo, así que aquí hay un poco más. es de esperar que la información sea más clara y que las personas puedan proporcionar una respuesta lo más precisa posible.
La intención es crear un servicio seguro y anónimo para respaldar la aplicación, que puede ser ejecutado por cualquier persona, en cualquier lugar. La aplicación y la API son de código abierto y, por lo tanto, cualquier persona que desee proporcionar su espacio de servidor para otros usuarios de la aplicación puede ejecutar su propia instancia de la API. Los usuarios de la aplicación pueden apuntarla a la URL de la API de su elección, lo que les permite usar cualquier instancia pública de la API, o incluso alojar una instancia en su propio servidor que solo ellos pueden usar.
Debido a que los datos del usuario pueden estar en cualquier servidor público, es importante que los datos estén cifrados del lado del cliente y que el usuario nunca envíe su contraseña de texto simple por el cable, en caso de que el propietario del servidor API (o cualquier otra persona) desee Para descifrar los datos de usuario que se alojan. El servicio es anónimo por razones de seguridad y conveniencia, por lo tanto, el usuario de la aplicación no tiene que proporcionar una dirección de correo electrónico ni ninguna otra información de identificación, simplemente hace clic en un botón de la aplicación y sus datos se cifran con su contraseña, que se envía a la API junto con su contraseña de hash:
Ejemplo de publicación del cuerpo:
{
"data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
"passwordHash":"d4de34f15aeadfb34bdf1fbbd57134b2baeb142c"
}
Respuesta:
{
"id":"507f191e810c19729de860ea",
"lastUpdated":"2016-07-06T12:43:16.866Z"
}
La entrada mongodb se vería así:
{
"id": "507f191e810c19729de860ea",
"passwordHash": "d4de34f15aeadfb34bdf1fbbd57134b2baeb142c",
"data": "DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
"lastUpdated": "2016-07-06T12:43:16.866Z"
}
Un usuario puede recuperar sus datos con una solicitud GET para /api/data/{id}/{passwordHash}
, así que para el ejemplo anterior:
/api/data/507f191e810c19729de860ea/d4de34f15aeadfb34bdf1fbbd57134b2baeb142c
Respuesta:
{
"data":"DWCx6wR9ggPqPRrhU4O4oLN5P09onApoAULX4Xt+ckxswtFNH/QQ+Y/RgxdU+8+8/muo4jo/jKnHssSezvjq6aPvYK+EAzAoRmXenAgUwHOjbiAXFqF8gScbbuLRlF0MsTKn/puIyFnvJd...",
"lastUpdated":"2016-07-06T12:43:16.866Z"
}
Dado que el valor de id (ID de objeto MongoDB) no es demasiado complejo, un usuario malintencionado puede potencialmente adivinar la identificación de otra persona y recuperar sus datos a través de la API. Por esa razón, decidí usar el ID junto con el hash de la contraseña del usuario como la clave para que a un usuario malintencionado le resulte más difícil adivinar la clave exclusiva de otra persona. Sin embargo, si solo utilizara la identificación del objeto como clave e incluso si pudieran adivinar la identificación de otro usuario, solo recuperarían sus datos cifrados (no el hash de la contraseña), que luego necesitarían descifrar antes de leer los datos. ¿Sería esta una mejor alternativa para almacenar el hash de contraseña? Irónicamente, esto resolvería el problema de bcrypt como si no estuviera almacenando los hashes de contraseña en el servidor, no necesitaría hash la contraseña (utilizada para cifrar los datos del lado del cliente) en absoluto ...
En conclusión, la pregunta en relación con mi aplicación / api es mucho más compleja que la pregunta en curso, pero realmente no pude pensar en cómo encuadrarla correctamente (tal vez necesito cambiar la pregunta ). Sin embargo, si alguien tiene alguna opinión sobre los aspectos de seguridad de mi enfoque teniendo en cuenta los requisitos, le agradecería mucho la aportación.