Pregunta

¿Cuál es su método / tipo de datos preferido para almacenar contraseñas en una base de datos (preferiblemente SQL Server 2005)? La forma en que lo he estado haciendo en varias de nuestras aplicaciones es usar primero las bibliotecas de encriptación .NET y luego almacenarlas en la base de datos como binario (16). ¿Es este el método preferido o debo utilizar un tipo de datos diferente o asignar más espacio que 16?

¿Fue útil?

Solución

Almaceno el hash salado equivalente a la contraseña en la base de datos y nunca la contraseña en sí, luego siempre comparo el hash con el valor generado por el usuario.

Es demasiado peligroso almacenar los datos de la contraseña literal en cualquier lugar. Esto hace que la recuperación sea imposible, pero cuando alguien olvida o pierde una contraseña, puede ejecutar algunas comprobaciones y crear una nueva contraseña.

Otros consejos

EL método preferido: nunca almacene contraseñas en su base de datos. Sólo hashes de los mismos. Añadir sal al gusto.

Hago lo mismo que has descrito, excepto que se almacena como una cadena. Base64 codifica el valor binario encriptado. La cantidad de espacio para asignar depende del algoritmo de cifrado / intensidad de cifrado.

Creo que lo estás haciendo bien (dado que usas un Salt ) .

  1. almacena el hash de la contraseña con sal, como bcrypt (nounce + pwd). Es posible que prefiera bcrypt sobre SHA1 o MD5 porque se puede ajustar para que requiera un uso intensivo de la CPU, por lo que hace que el ataque de fuerza bruta sea más prolongado.
  2. agregue un captcha al formulario de inicio de sesión después de algunos errores de inicio de sesión (para evitar ataques de fuerza bruta)
  3. si su aplicación tiene un " olvidó mi contraseña " enlace, asegúrese de que no envíe la nueva contraseña por correo electrónico, sino que debe enviar un enlace a una página (segura) que le permita al usuario definir una nueva contraseña (posiblemente solo después de la confirmación de cierta información personal, como el nacimiento del usuario) fecha, por ejemplo). Además, si su aplicación le permite al usuario definir una nueva contraseña, asegúrese de pedirle al usuario que confirme la contraseña actual.
  4. y, obviamente, asegure el formulario de inicio de sesión (normalmente con HTTPS) y los servidores mismos

Con estas medidas, las contraseñas de sus usuarios estarán bastante bien protegidas contra:

  1. = > ataques de diccionario fuera de línea
  2. = > ataques de diccionario en vivo
  3. = > ataques de denegación de servicio
  4. = > todo tipo de ataques!

Dado que el resultado de una función hash es una serie de bytes en el rango de 0 a 255 (o -128 a 127, dependiendo de la firma de su tipo de datos de 8 bits), almacenándola como un campo binario sin formato hace El más sensato, ya que es la representación más compacta y no requiere pasos adicionales de codificación y decodificación.

Algunas bases de datos o controladores no tienen un gran soporte para tipos de datos binarios, o a veces los desarrolladores simplemente no están lo suficientemente familiarizados con ellos para sentirse cómodos. En ese caso, es aceptable utilizar una codificación de binario a texto como Base-64 o Base-85, y almacenar el texto resultante en un campo de caracteres.

El tamaño del campo necesario está determinado por la función hash que utiliza. MD5 siempre genera 16 bytes, SHA-1 siempre genera 20 bytes. Una vez que selecciona una función hash, normalmente se queda atascado con ella, ya que cambiar requiere un restablecimiento de todas las contraseñas existentes. Por lo tanto, usar un campo de tamaño variable no te compra nada.


Respecto a la " mejor " Para realizar el hashing, he intentado proporcionar muchas respuestas a otras preguntas de SO sobre ese tema:

Utilizo el hash sha del nombre de usuario, un guid en la configuración web y la contraseña, almacenados como varchar (40). Si quieren usar fuerza bruta / diccionario, también deberán piratear el servidor web para la guía. El nombre de usuario rompe la creación de una tabla arco iris en toda la base de datos si encuentran la contraseña. Si un usuario desea cambiar su nombre de usuario, simplemente reinicio la contraseña al mismo tiempo.

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);

Un simple hash de la contraseña, o incluso (salt + contraseña) generalmente no es adecuado.

ver:

http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/

y

http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords

Ambos recomiendan los algoritmos bcrypt. Las implementaciones gratuitas se pueden encontrar en línea para los idiomas más populares.

Puedes usar múltiples hashes en tu base de datos, solo requiere un poco de esfuerzo extra. Sin embargo, vale la pena si cree que existe la posibilidad más remota que necesitará para admitir formatos adicionales en el futuro. A menudo usaré entradas de contraseña como

{hashId} $ {salt} $ {contraseña hash}

donde " hashId " es solo un número que uso internamente para reconocer que, por ejemplo, estoy usando SHA1 con un patrón de hash específico; " sal " es una sal aleatoria codificada en base64; y " contraseña hash " Es un hash codificado en base64. Si necesita migrar hashes, puede interceptar personas con un formato de contraseña anterior y hacer que cambien su contraseña la próxima vez que inicien sesión.

Como han mencionado otros, debes tener cuidado con tus hashes ya que es fácil hacer algo que no es realmente seguro, por ejemplo, H (sal, contraseña) es mucho más débil que H (contraseña, sal), pero al mismo tiempo desea equilibrar el esfuerzo puesto en esto con el valor del contenido del sitio. A menudo usaré H (H (contraseña, sal), contraseña).

Finalmente, el costo de usar contraseñas codificadas en base64 es modesto en comparación con los beneficios de poder usar varias herramientas que esperan datos de texto. Sí, deberían ser más flexibles, pero ¿estás listo para decirle a tu jefe que no puede usar su herramienta de terceros favorita porque quieres guardar algunos bytes por registro? :-)

Editado para agregar otro comentario: si sugiero usar deliberadamente un algoritmo que haya quemado incluso una décima de segundo hashing con cada contraseña, tendré la suerte de que me echen a reír fuera de la oficina de mi jefe. (¿No es tan afortunado? Él anotaría algo para discutir en mi próxima revisión anual). Quemar ese momento no es un problema cuando tiene docenas, o incluso cientos, de usuarios. Si está presionando a usuarios de 100k, normalmente tendrá a varias personas iniciando sesión al mismo tiempo. Necesitas algo rápido y fuerte, no lento y fuerte. El " pero ¿qué pasa con la información de la tarjeta de crédito? & Quot; en el mejor de los casos, es falso, ya que la información almacenada de la tarjeta de crédito no debería estar en ningún lugar cerca de su base de datos habitual, y la aplicación la cifraría de todos modos, no los usuarios individuales.

Si está trabajando con ASP.Net, puede usar la API de membresía incorporada.

Es compatible con muchos tipos de opciones de almacenamiento, incluyendo; hash unidireccional, cifrado bidireccional, md5 + sal. http://www.asp.net/learn/security para obtener más información.

Si no necesitas nada demasiado sofisticado, esto es genial para los sitios web.

Si no está utilizando ASP.Net, aquí hay un buen enlace a algunos artículos de 4guys y codeproject

http://aspnet.4guysfromrolla.com/articles/081705-1.aspx http://aspnet.4guysfromrolla.com/articles/103002-1.aspx http://www.codeproject.com/KB/security/SimpleEncryption.aspx

Dado que su pregunta es sobre el método de almacenamiento & amp; tamaño voy a abordar eso.

El tipo de almacenamiento puede ser binario o representación de texto (la base64 es la más común). Binario es más pequeño pero me resulta más fácil trabajar con texto. Si está haciendo salazón por usuario (diferente sal por contraseña), entonces es más fácil almacenar salt + hash como una única cadena combinada.

El tamaño depende del algoritmo hash. La salida de MD5 es siempre de 16 bytes, SHA1 siempre es de 20 bytes. SHA-256 & amp; SHA-512 son 32 y amp; 64 bytes respectivamente. Si está utilizando codificación de texto, necesitará un poco más de almacenamiento, dependiendo del método de codificación. Tiendo a usar Base64 porque el almacenamiento es relativamente barato. Base64 requerirá un campo aproximadamente un 33% más grande.

Si tiene sal por usuario, también necesitará espacio para el hash. Poniéndolo todo junto a 64 bits de sal + hash SHA1 (160 bits) codificado en base64 toma 40 caracteres, así que lo guardo como char (40).

Por último, si quieres hacerlo bien, no deberías usar un solo hash, sino una función de derivación de claves como RBKDF2. Los hashes SHA1 y MD5 son increíblemente rápidos. Incluso una aplicación de un solo subproceso puede hacer hash de 30K a 50K de contraseñas por segundo, es decir, hasta 200K de contraseñas por segundo en una máquina de cuatro núcleos. Las GPUs pueden capturar de 100x a 1000x tantas contraseñas por segundo. Con velocidades como esa, el ataque de fuerza bruta se convierte en un método de intrusión aceptable. RBKDF2 le permite especificar el número de iteraciones para ajustar la forma en que " lento " tu hash es El punto no es 'poner el sistema de rodillas, sino elegir una serie de iteraciones para que pueda limitar el límite superior del rendimiento de hash (por ejemplo, 500 hashes por segundo). Un método de prueba futuro sería incluir el número de iteraciones en el campo de contraseña (iteraciones + sal + hash). Esto permitiría aumentar las iteraciones en el futuro para mantener el ritmo con procesadores más potentes. Para ser aún más flexible, use varchar para permitir hashes potencialmente más grandes / alternativos en el futuro.

La implementación de .Net es RFC2892DeriveBytes http://msdn.microsoft.com/en-us /library/system.security.cryptography.rfc2898derivebytes.aspx

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top