2009-06-03 38 views
30

Estoy usando Mysql y suponía que era mejor separar la información personal de un usuario y su nombre de usuario y contraseña en dos tablas diferentes y luego solo hacer referencia entre los dos .Cómo almacenar mejor la información de usuario y el nombre de usuario y la contraseña

Nota: Para aclarar mi publicación, entiendo las técnicas de seguridad de la contraseña (hash, salt, etc.). Solo sé que si sigo prácticas de otras partes de mi vida (inversión, copia de seguridad de datos, incluso almacenamiento personal), en el peor de los casos (tabla compuesta o incendio) que tener información dividida entre tablas proporciona la posibilidad de proteger su datos adicionales.

+0

Solo para aclarar; ¿Desea saber cómo almacenar correctamente las contraseñas en la base de datos, o simplemente desea saber si los datos del perfil de usuario deben separarse de los datos de la cuenta base? Respondí por el primero, pero al volver a leer la pregunta, pareces querer lo último. – Rob

+1

La mayoría de las respuestas se centran en el método de contraseñas hashing y salar. Esta es información que vale la pena, pero no aborda la pregunta del OP. –

+0

Sí, voy a guardar la contraseña usando sha1 y una salazón. – Tim

Respuesta

35

No guarde las contraseñas. Si alguna vez está sentado en un disco, puede ser robado. En cambio, almacena hashes de contraseña. Use the right hashing algorithm, como bcrypt (que incluye una sal).

EDIT: El OP ha respondido que él entiende el problema anterior.

No es necesario almacenar la contraseña en una tabla físicamente diferente del inicio de sesión. Si una tabla de base de datos está en peligro, no es un gran salto para acceder a otra tabla en esa misma base de datos.

Si está suficientemente preocupado por la seguridad y la seguridad en profundidad, puede considerar almacenar las credenciales del usuario en un almacén de datos completamente independiente de los datos de su dominio. Un enfoque, comúnmente hecho, es almacenar credenciales en un servidor de directorio LDAP. Esto también podría ayudar con cualquier trabajo de inicio de sesión único que realice más tarde.

+1

Tiene toda la razón, MD5 simplemente no es lo suficientemente fuerte. –

+3

+1 para todo menos la recomendación de SHA. SHA y MD5 están en la misma clase insuficiente de alias de hash: desde el punto de vista de la seguridad, ambos palidecen en comparación con el hashing adaptativo, como menciona Rob a continuación. –

+0

Realmente no responde la pregunta. –

14

No hay nada de malo en colocarlos en la misma tabla. De hecho, sería mucho más rápido, así que lo recomendaría mucho. No sé por qué querrías dividirlo.

+1

Tengo serias dudas de que sea más rápido, ya que la comprobación de nombre/contraseña y datos de usuario se realizaría en partes muy diferentes de cualquier aplicación, y se realizaría en momentos muy diferentes. piense: ¿necesita los datos válidos para cada rechazo de inicio de sesión? después de aceptarlo, ¿necesita verificar la contraseña cada vez que lea el perfil? por supuesto, generalmente no me molesto, y lo pongo todo junto. pero es solo por simplicidad, no por rendimiento. – Javier

+2

No, porque necesitaría hacer UNIONES cada vez que obtenga los datos del usuario. O eso o tendría mucha información duplicada (por ejemplo, nombre de usuario e ID almacenados en ambos, etc.), ninguno de los cuales es óptimo. De cualquier manera, no hay ninguna razón para dividirlo en dos tablas diferentes; simplemente no tiene ningún sentido, ya sea por rendimiento o simplicidad. –

+1

+1 Esta es la única respuesta (hasta ahora) que responde a la pregunta del OP. –

0

Debe almacenarlos en la misma tabla y usar cifrado unidireccional. MD5 funcionará, pero es débil, por lo que podría considerar algo como SHA1 u otro método. No hay beneficio para almacenar los 2 artículos en tablas separadas.

+1

No existe el cifrado unidireccional; el término es hash criptográfico. MD5 y SHA1 son algoritmos de hash rápidos y no son una buena idea para el hashing de contraseñas. Deberías salar el hash con un código aleatorio almacenado en la base de datos. – Rob

+0

http://en.wikipedia.org/wiki/One-way_encryption De hecho, la opción de usar un término sobre otro no es tan importante como la idea transmitida, y muchas personas usan el término 'Encriptación unidireccional' 'y se entienden comúnmente. –

7

Voy a intentar responder a su pregunta original. Tener todo en una sola mesa está bien a menos que solo tenga mucha información personal para reunir. En ese caso, puede tener sentido dividirlo. Esa decisión debe tomarse en función de la cantidad de información personal con la que está tratando y la frecuencia con la que debe accederse.

yo diría que la mayoría de las veces que me gustaría hacer algo como esto en una sola tabla:

UserID, FirstName, LastName, Email, Password, TempPassword 

... Pero si usted está reuniendo mucho más que eso. Digamos que está reuniendo teléfono, fax, fecha de nacimiento, biografía, etc., etc. Y si la mayoría de esa información rara vez se accede, probablemente la pondría en su propia mesa y la conectaría con una relación de uno a uno. Después de todo, cuantas menos columnas tenga en una tabla, más rápidas serán sus consultas contra esa tabla. Y a veces tiene sentido simplificar las tablas a las que más se accede. Sin embargo, hay un golpe de rendimiento con el JOIN cada vez que necesitas acceder a esa información personal, así que eso es algo que deberás considerar.

EDITAR - Sabes qué, solo pensé en algo. Si crea un índice en el campo de nombre de usuario o correo electrónico (lo que prefiera), eliminará casi por completo el inconveniente de rendimiento de crear tantas columnas en una tabla de usuario. Lo digo porque cada vez que inicies sesión, la cláusula WHERE será extremadamente rápida para encontrar el nombre de usuario si tiene un índice y no importará si tienes 100 columnas en esa tabla. Así que he cambiado mi opinión. Lo pondría todo en una mesa.;)

En cualquier caso, dado que la seguridad parece ser un tema popular, la contraseña debe ser un valor hash. Sugeriría SHA1 (o SHA256 si realmente te preocupa). TempPassword también debe usar un hash y solo está ahí para la funcionalidad de contraseña olvidada. Obviamente, con un hash no puede descifrar y enviar al usuario su contraseña original. En su lugar, generan una contraseña temporal con la que pueden iniciar sesión y luego les obligan a cambiar su contraseña nuevamente después de iniciar sesión.

+0

No almacene la contraseña temporal. Es un hoyo. –

+0

La contraseña temporal también debe ser un hash SHA1. ¿Cómo es eso un hoyo? –

+0

¿qué sugieres en su lugar? – nickf

3

En primer lugar, para indicar el (con suerte) obvio, si puede de ninguna manera evitar el almacenamiento de nombres de usuario y contraseñas; es una gran responsabilidad y si se infringe su tienda de credenciales, puede proporcionar acceso a muchos otros lugares para los mismos usuarios (debido al uso compartido de contraseñas).

Si debe almacenar credenciales:

  • No almacene una forma reversible; almacenar un hash utilizando un algoritmo reconocido como SHA-256. Utilice el software criptográfico de una fuente de confianza de buena reputación. NO INTENTE RODAR SU PROPIO, ES PROBABLE QUE LO HAGA EQUIVOCADO.
  • Para cada conjunto de credenciales, almacene una sal junto con los datos hash; esto se usa para "cebar" el hash de modo que dos contraseñas idénticas no produzcan el mismo hash, ya que eso revela que las contraseñas son las mismas.
  • Utilice un generador aleatorio seguro. La aleatoriedad débil es la causa principal de las fallas de seguridad relacionadas con el cifrado, no de los algoritmos de cifrado.

Si debe almacenar credenciales reversibles:

  • elegir un buen algoritmo de cifrado - AES-256, 3DES (fecha), o un sistema de cifrado de clave pública. Utilice el software criptográfico de una fuente de confianza de buena reputación. NO INTENTE RODAR SU PROPIO, ES PROBABLE QUE LO HAGA EQUIVOCADO.
  • Para cada conjunto de credenciales, almacene una sal (no encriptada) junto con los datos cifrados; esto se usa para "cebar" el cifrado de modo que dos contraseñas idénticas no produzcan el mismo texto de cifrado, ya que eso revela que las contraseñas son las mismas.
  • Utilice un generador aleatorio seguro. La aleatoriedad débil es la causa principal de las fallas de seguridad relacionadas con el cifrado, no de los algoritmos de cifrado.
  • Almacene las claves de cifrado/descifrado por separado de su base de datos, en un archivo seguro de O/S, accesible solo para su perfil de tiempo de ejecución de las aplicaciones. De esta forma, si su base de datos se infringe (por ejemplo, mediante inyección SQL) su clave no es automáticamente vulnerable, ya que eso requeriría acceso a la unidad de disco duro en general. Si su O/S es compatible con el cifrado de archivos vinculado a un perfil, úselo: solo puede ayudar y, por lo general, es transparente (por ejemplo, cifrado NTFS).
  • Si es posible, guarde las claves cifradas con una contraseña principal. Esto generalmente significa su aplicación. necesitará la contraseña introducida al inicio; no es bueno proporcionarla en un parámetro de una secuencia de comandos, ya que si se rompe su HDD, debe suponer que se pueden ver tanto el archivo de la clave como la secuencia de comandos.
  • Si el nombre de usuario no es necesario para localizar el registro de la cuenta, cifre tanto el nombre de usuario como la contraseña.
17

Las contraseñas deben almacenarse como un hash criptográfico, que es una operación no reversible que impide leer el texto sin formato. Al autenticar usuarios, la entrada de contraseña se somete al mismo proceso de hash y se comparan los hashes.

Evite el uso de un hash rápido y barato como MD5 o SHA1; el objetivo es encarecer que un atacante calcule tablas de arcoiris (basadas en colisiones hash); un hash rápido contrarresta esto. El uso de un hash caro no es un problema para los escenarios de autenticación, ya que no tendrá ningún efecto en una sola ejecución del hash.

Además de hash, sal el hash con un valor generado aleatoriamente; un nonce, que luego se almacena en la base de datos y se concatena con los datos antes de hash. Esto aumenta la cantidad de combinaciones posibles que deben generarse al calcular las colisiones, y por lo tanto aumenta la complejidad general del tiempo de generación de tablas de arcoiris.

Su columna hash de contraseña puede tener una longitud fija; su hash criptográfico debe generar valores que pueden codificarse en una longitud fija, que será la misma para todos los hashes.

Siempre que sea posible, evite rodar su propio mecanismo de autenticación de contraseña; use una solución existente, como bcrypt.

Puede encontrar una excelente explicación de cómo manejar contraseñas, y con qué debe preocuparse, en http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes.

Como nota final, recuerde que si un atacante obtiene acceso a su base de datos, entonces su preocupación inmediata debería ser con cualquier información sensible o de identificación personal a la que puedan tener acceso, y cualquier daño que puedan haber hecho.

+2

La publicación del blog se ha movido a http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html – jwhitlock

+1

+1 para 'bcrypt' – dave1010

+0

nunca use bcrypt Vea aquí http://bugs.debian.org/700758 – nikoss

2

En mi experiencia personal, el almacenamiento de la información personal y la información de inicio de sesión en bases de datos individuales es la mejor práctica en este caso. La razón por la cual debe realizarse una inyección SQL es limitada (a menos que el infiltrado conozca el diseño interno de su base de datos) a la tabla a la que pertenecen los datos, en lugar de proporcionar acceso a todo el conglomerado de datos.

Sin embargo, tenga en cuenta que esto puede deberse a la necesidad de realizar más consultas, por lo tanto, un golpe de rendimiento.

+2

O podría ser un programador cuidadoso y prevenir ataques de inyección SQL en primer lugar. ;) –

+0

Por supuesto = P Naturalmente, para cada contramedida implementada, hay una elusión, sin embargo. Así que también puede reducir las pérdidas y hacer que sea más difícil obtener información no relacionada. – Jason

2

¿Todos estos datos siempre tendrán una relación 1: 1 con el usuario? Si puede permitir que los usuarios tengan varias direcciones, números de teléfono, etc., puede dividir la información personal en una tabla separada.

Cuestiones relacionadas