Almacenamiento de usuario y contraseña en una base de datos

Estoy creando un software con usuario + contraseña. Después de la autenticación, el usuario puede acceder a algunos servicios semipúblicos, pero también puede cifrar algunos archivos a los que solo el usuario puede acceder.

El usuario debe almacenarse tal cual, sin modificaciones, si es posible. Después de la autenticación, el usuario y la contraseña se guardan en la memoria siempre que el software se esté ejecutando (no sé si eso también está bien).

La pregunta es ¿cómo debo almacenar esta combinación de usuario y contraseña en una base de datos potencialmente insegura?

Realmente no entiendo que debo exponer.

Digamos que creo una clave mejorada como esta:

 Salt = cadena de 32 caracteres al azar (¿está bien?)
 clave = hash (contraseña usr + sal)
 de 1 a 65000 do
   clave = hash (clave + contraseña usr + sal)

¿Debo almacenar el [usuario de texto sin formato], [la clave mejorada] y [la sal] en la base de datos?

Además, ¿qué debo usar para cifrar (con AES o Blowfish) algunos archivos con una nueva contraseña cada vez? ¿Debo generar una nueva sal y crear una nueva clave mejorada usando (la contraseña almacenada en la memoria del progtwig + la sal)? Y en este caso, si almaceno el archivo cifrado en la base de datos, probablemente solo debería almacenar el salt. La base de datos es la misma que donde almaceno la combinación de usuario y contraseña.

El archivo solo se puede descifrar si alguien puede generar la clave, pero no conoce la contraseña. Correcto ?

Uso Python con PyCrypto, pero no es realmente importante, un ejemplo general está bien. He leído algunas preguntas similares, pero no son muy explícitas.

¡Muchas muchas gracias!

Crypto es difícil de entender, es bueno que hagas preguntas.

Almacenamiento de contraseñas: las contraseñas deben estar escritas con un algoritmo de estiramiento clave . Normalmente, desea utilizar una biblioteca en lugar de implementarla usted mismo. Los algoritmos de estiramiento de teclas están diseñados para masticar los ciclos del procesador, por lo que es bueno evaluarlos con un código C agradable. Si está en un sistema Linux con glibc , puede usar el módulo crypt.crypt (lea man crypt ):

 import crypt encrypted = crypt.crypt(password, '$6$' + salt + '$') 

Esto devuelve una cadena ASCII que puede almacenar de forma segura en su base de datos. ( $6$ es una extensión de glibc que usa una función de estiramiento de teclas basada en SHA-512. Si no tiene esta extensión, entonces no use crypt.crypt ). (Editar: el algoritmo es muy similar al que mencionaste en tu pregunta. Sin embargo, la mejor práctica generalmente es dejar que una biblioteca haga esas cosas en lugar de rodar las tuyas).

Cifrado de archivos: No hagas esto tú mismo. Instale GnuPG (o scrypt, bcrypt, ncrypt, lo que tenga). Hay algunas cosas que pueden salir mal fácilmente cuando diseñas tu propia forma de cifrar archivos. Estas herramientas utilizan las funciones de derivación de clave, los hashes de autenticación y los modos de cifrado adecuados sin ninguna configuración adicional. No son bibliotecas de Python, sino ejecutables, por lo que tendrá que escribir un contenedor que use el módulo de subprocess .

Contraseñas en la memoria: no. Una vez que haya verificado la contraseña del usuario con su base de datos de contraseñas, convierta la contraseña en una clave usando una función de derivación de claves. Luego puede usar la clave para desbloquear archivos encriptados, pero ya no puede usarla para recuperar la contraseña original.

Si usa una sal diferente para cada usuario, debe almacenarla en algún lugar (idealmente en un lugar diferente). Si usa la misma sal para cada usuario, puede codificarla en su aplicación, pero puede considerarse menos segura. Si no guarda la sal, no podrá hacer coincidir una contraseña determinada con la de su base de datos.

El objective de la sal es hacer que los ataques de fuerza bruta o dictamen sean mucho más difíciles. Por eso es más seguro si se almacena por separado, para evitar que alguien tenga contraseñas de hash y las sales correspondientes.