La mejor manera de almacenar la contraseña en la base de datos [cerrada]

476

Estoy trabajando en un proyecto que debe tener autenticación (nombre de usuario y contraseña)

También se conecta a una base de datos, así que pensé que almacenaría el nombre de usuario y la contraseña allí. Sin embargo, parece que no es una buena idea tener contraseñas como solo un campo de texto en una tabla ubicada en la base de datos.

Estoy usando C # y me conecto a un servidor express 2008. ¿Alguien puede sugerir (con tantos ejemplos como sea posible) cuál sería la mejor manera de almacenar este tipo de datos?

PD: Estoy abierto a la idea de que esta información no se almacene en la base de datos si se puede proporcionar una buena razón

Choque893
fuente
1
Hagas lo que hagas, si vas con cifrado, no guardes la clave en el código como se menciona en un póster anterior. Eso es solo una mala práctica.
Woody
12
'¿Cómo hacer las contraseñas, verdad?' Es una pregunta vital. Es un problema difícil y los errores tienen graves consecuencias (recuerde lo que le sucedió a Tesco y LinkedIn). Creo que esta pregunta debería reabrirse en programmers.stackexchange.com
Coronel Panic
2
Es mejor atenerse a los estándares: consulte en.wikipedia.org/wiki/PBKDF2 Solo tiene que encontrar una implementación en su idioma
Boris Treukhov
55
Esta pregunta se responde ampliamente en el foro de seguridad
gioele

Respuestas:

406

Tiene razón en que almacenar la contraseña en un campo de texto sin formato es una idea horrible . Sin embargo, en lo que respecta a la ubicación , para la mayoría de los casos se encontrará (y sinceramente no puedo pensar en ningún contraejemplo) almacenar la representación de una contraseña en la base de datos es lo correcto. Por representación me refiero a que desea descifrar la contraseña utilizando una sal (que debería ser diferente para cada usuario) y un algoritmo seguro de 1 vía y almacenar eso , desechando la contraseña original. Luego, cuando desee verificar una contraseña, debe seleccionar el valor hash (utilizando el mismo algoritmo hash y salt) y compararlo con el valor hash de la base de datos.

Entonces, si bien es bueno que esté pensando en esto y es una buena pregunta, en realidad es un duplicado de estas preguntas (al menos):

Para aclarar un poco más sobre la sal, el peligro con simplemente descifrar una contraseña y almacenarlo es que si un intruso obtiene su base de datos, aún puede usar lo que se conoce como tablas del arco iris para poder "descifrar" el contraseña (al menos las que aparecen en la tabla del arco iris). Para evitar esto, los desarrolladores agregan una sal a las contraseñas que, cuando se hace correctamente, hace que los ataques de arco iris sean simplemente imposibles de hacer. Tenga en cuenta que un error común es simplemente agregar la misma cadena única y larga a todas las contraseñas; Si bien esto no es horrible , es mejor agregar sales únicas a cada contraseña. Lee esto para más.

Paolo Bergantino
fuente
40
Me refería a almacenar la contraseña en la base de datos en lugar de almacenarla en otro lugar. Tomar esa oración fuera de contexto hace que parezca que estoy apoyando el almacenamiento de contraseñas simples, si lees el resto, obviamente no lo hago.
Paolo Bergantino
14
No solo es eso lo que dije, sino que lo dirigí a una gran cantidad de publicaciones que discuten sobre las sales y demás ...
Paolo Bergantino
1
@Paolo Bergantino: ¿estás seguro de que no hay un error tipográfico en tu publicación? Dice "Para la mayoría de los casos con los que se encontrará (y sinceramente no puedo pensar en ningún contraejemplo), almacenar la contraseña en la base de datos es lo correcto". ??? Parece contradecir sus comentarios
Mitch Wheat
3
Lo que dijo Paolo se contradice directamente. Un hash salado de una contraseña no es una contraseña. Almacenar un hash salado de la contraseña en la base de datos no es almacenar la contraseña en la base de datos. El cuerpo de la respuesta es perfectamente apropiado, pero su primera oración es extremadamente engañosa.
Robert Rossney
40
@Robert: Eso se está acercando peligrosamente a un juego de semántica insignificante, pero igual lo arreglaré ...
Paolo Bergantino
54

Antecedentes Nunca ... realmente ... necesita saber la contraseña del usuario. Solo desea verificar que un usuario entrante conozca la contraseña de una cuenta.

Hash It: almacene las contraseñas de usuario hash (cifrado unidireccional) a través de una fuerte función hash. La búsqueda de "contraseñas de cifrado de c #" ofrece muchos ejemplos.

Consulte el creador de hash SHA1 en línea para obtener una idea de lo que produce una función hash (pero no use SHA1 como función hash, use algo más fuerte como SHA256).

Ahora, una contraseña con hash significa que usted (y los ladrones de bases de datos) no deberían poder revertir ese hash en la contraseña original.

Cómo usarlo: Pero, usted dice, ¿cómo uso esta contraseña mezclada almacenada en la base de datos?

Cuando el usuario inicia sesión, le entregará el nombre de usuario y la contraseña (en su texto original). Simplemente use el mismo código hash para ingresar esa contraseña ingresada y obtener la versión almacenada.

Entonces, compare las dos contraseñas hash (hash de la base de datos para el nombre de usuario y la contraseña escrita y hash). Puede saber si "lo que escribieron" coincide "con lo que el usuario original ingresó para su contraseña" comparando sus valores hash.

Crédito adicional:

Pregunta: Si tuviera su base de datos, ¿no podría simplemente tomar una galleta como John the Ripper y comenzar a hacer hash hasta encontrar coincidencias con sus contraseñas hash almacenadas? (dado que los usuarios eligen palabras cortas de diccionario de todos modos ... debería ser fácil)

Respuesta: Sí ... sí que pueden.

Por lo tanto, debe 'sal' sus contraseñas. Ver el artículo de Wikipedia sobre sal

Consulte el ejemplo de "Cómo hacer hash de datos con sal" C #

joej
fuente
14
Buena publicación, excepto por una cosa: md5 y sha1 se han roto. Probablemente deberías usar un algoritmo más fuerte, como quizás la familia SHA2.
Paolo Bergantino
3
Gracias Paolo, tienes razón. Como el uso de SHA2 es tan fácil como usar MD5 y SHA1, utilice el algoritmo hash más fuerte.
joej
55
SHA-1 no se ha roto. Pero parafraseando a Bruce Schneier: Camina, no corras, hacia SHA-2.
Ian Boyd
3
"Por lo tanto, debe 'sal' sus contraseñas" ... Pero la sal generalmente se almacena en la base de datos junto con la contraseña, entonces, ¿cómo ayuda eso? El atacante simplemente tiene que agregar sal a las frases de ataque del diccionario con las que está probando. ¿Cómo es eso más seguro que no revelará contraseñas duplicadas?
trusktr
44
@joej "Nunca ... realmente ... necesitas saber la contraseña del usuario", esa es una suposición muy miope. Hay muchos tipos de aplicaciones en las que es realmente necesario tener una contraseña almacenada de forma que pueda recuperarse. Por ejemplo, una aplicación que necesita iniciar sesión con frecuencia en otro sistema con credenciales almacenadas, proporcionadas y actualizadas por un usuario.
Francisco Zarabozo
29

Como un hash salado endurecido con clave, utilizando un algoritmo seguro como sha-512.

nilamo
fuente
66
En mi opinión, siempre debes usar algoritmos lentos (como Blowfish, por ejemplo) para almacenar contraseñas. Este informe es una respuesta mucho mejor: security.stackexchange.com/questions/211/… . Solo ponlo aquí, porque esta página todavía aparece en lo alto de los resultados de búsqueda.
Dynom
2
Seguir este consejo para el almacenamiento de contraseñas lo haría lamentablemente mal.
mlissner
27

La mejor práctica de seguridad no es almacenar la contraseña (ni siquiera encriptada), sino almacenar el hash salado (con una sal única por contraseña) de la contraseña encriptada.

De esa manera es (prácticamente) imposible recuperar una contraseña de texto sin formato.

Trigo Mitch
fuente
11
Wayne, al salar antes de calcular el hash, la tabla del arco iris es efectivamente derrotada, siempre que la sal tenga el tamaño suficiente.
Mike Rosenblum
12
@Wayne Hartman: No es así. Si el valor de sal está expuesto, debe generar una nueva tabla de arco iris para ese valor de sal específico. El objetivo de una tabla de arco iris es tener valores hash calculados de antemano. Y nadie tendrá una mesa arcoiris para su sal específica.
Ian Boyd
10

Recomiendo leer los artículos Suficiente con las tablas del arco iris: lo que necesita saber sobre los esquemas de contraseña segura [enlace inactivo , copia en el Archivo de Internet ] y Cómo almacenar una contraseña de forma segura .

Muchos codificadores, incluido yo mismo, creen que entienden la seguridad y el hash. Lamentablemente, la mayoría de nosotros simplemente no lo hacemos.

zebrabox
fuente
1
@Johan Parece que el enlace ahora está roto, lo cual es una pena. Aquí hay una alternativa codahale.com/how-to-safely-store-a-password
zebrabox
6

Puede que esté un poco fuera de tema, ya que mencionó la necesidad de un nombre de usuario y una contraseña, y mi comprensión del problema no es la mejor, pero ¿OpenID es algo que vale la pena considerar?

Si usa OpenID, entonces no terminará almacenando ninguna credencial si entiendo la tecnología correctamente y los usuarios pueden usar las credenciales que ya tienen, evitando la necesidad de crear una nueva identidad que sea específica para su aplicación.

Sin embargo, puede no ser adecuado si la aplicación en cuestión es solo para uso interno

RPX proporciona una manera fácil y agradable de integrar el soporte de OpenID en una aplicación.

Pitufo lisiado
fuente
Estoy de acuerdo en que openID estremece a las personas, pero para esta aplicación es una base de datos interna para una empresa, dudo que deseen que una persona mayor ingrese. tampoco es necesario el acceso web para que esta aplicación funcione correctamente, por lo que odiaría requerirla.
Crash893
3

En su escenario, puede echar un vistazo a la membresía asp.net, es una buena práctica almacenar la contraseña del usuario como una cadena hash en la base de datos. puede autenticar al usuario comparando la contraseña entrante cifrada con la almacenada en la base de datos.

Todo ha sido construido para este propósito, consulte la membresía asp.net

Ray Lu
fuente
1

Me gustaría MD5 / SHA1 la contraseña si no necesita poder revertir el hash. Cuando los usuarios inician sesión, puede cifrar la contraseña dada y compararla con el hash. Las colisiones de hash son casi imposibles en este caso, a menos que alguien obtenga acceso a la base de datos y vea un hash por el que ya tiene una colisión.

waiwai933
fuente
2
No usaría MD5 para el hash: básicamente está roto mscs.dal.ca/~selinger/md5collision
zebrabox
3
En realidad, no está tan roto. Lo que pueden hacer es encontrar el mismo valor hash para dos archivos diferentes. Lo que no pueden hacer es invertir el MD5 y obtener una contraseña que funcione.
waiwai933
2
Bueno, ¿eso no se rompería también entonces? Simplemente ingresa la otra contraseña que genera el mismo hash, y estás dentro. No necesitas saber la contraseña original. La forma de solucionar esto es si le da sal a la contraseña antes del hash.
mjuarez
2
@mjuarez si agrega sal a la contraseña antes de usar MD5, la colisión no importa porque no puede usar la otra contraseña
WiiMaxx