Contraseña segura Hashing

Necesito almacenar un hash de una sola contraseña en una aplicación .Net WinForms.

¿Cuál es la forma más segura de hacer esto?

En particular:

  • Sal, HMAC, o ambos?
  • ¿Cuánta sal?
  • ¿Cuántas iteraciones?
  • ¿Qué encoding? (La contraseña es simple ASCII)

Supongo que el algoritmo debe ser SHA512 o HMACSHA512.

Sal su hash con sal aleatoria segura de al menos 128bits o más, para evitar un ataque del arco iris y usar BCrypt , PBKDF2 o scrypt . PBKDF2 viene con la aprobación NIST .

Para citar: Archive.org: http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html

El problema es que MD5 es rápido. También lo son sus competidores modernos, como SHA1 y SHA256. La velocidad es un objective de diseño de un hash seguro moderno, porque los hashes son un bloque de construcción de casi todos los criptosistemas y, por lo general, se ejecutan a demanda por paquete o por mensaje.

La velocidad es exactamente lo que no quieres en una función de hash de contraseña.

Las funciones rápidas de validación de contraseñas son un problema, ya que pueden ser atacadas con la fuerza bruta. Con todos los algoritmos anteriores puedes controlar la “lentitud”

Puedo recomendar BCrypt.net . Muy fácil de usar y puedes sintonizar cuánto tiempo llevará hacer el hash, ¡lo cual es increíble!

 // Pass a logRounds parameter to GenerateSalt to explicitly specify the // amount of resources required to check the password. The work factor // increases exponentially, so each increment is twice as much work. If // omitted, a default of 10 is used. string hashed = BCrypt.HashPassword(password, BCrypt.GenerateSalt(12)); // Check the password. bool matches = BCrypt.CheckPassword(candidate, hashed); 

Para una implementación del lado del servidor con una gran cantidad de contraseñas, definitivamente debe usar un enfoque iterativo sintonizable como bcrypt. Este conocido artículo sobre el tema sigue siendo (la mayoría) relevante:

http://www.securityfocus.com/blogs/262

Para una sola contraseña en una aplicación independiente, donde la ubicación de almacenamiento probablemente ya esté asegurada por el sistema de autenticación del sistema, creo que es mucho menos importante. Un solo hash fuerte es probablemente lo suficientemente bueno, y agregar sal es tan fácil que no hay ninguna razón para no hacerlo.

RNGCryptoServiceProvider para generar un sal aleatorio, luego SHA512 la contraseña con el salt, y finalmente almacenar tanto el hash de contraseña como el sal correspondiente si luego quiere verificar que algún texto sea igual a la contraseña almacenada.

Hash y sal Si solo hash, podrías ser atacado por un ataque de arco iris (el reverso tiene búsqueda) y una sal hace esto mucho más difícil (la sal aleatoria sería lo mejor). Para tu encoding, probablemente quieras Base64 o Hex codificar tu matriz de bytes resultante . Si solo intenta almacenar la matriz de bytes como Unicode, podría correr el riesgo de perder algunos datos porque no todos los patrones son caracteres válidos. Esto también permite una forma más fácil de comparar hashes (simplemente compare la cadena base64 o hex cuando quiera validar en lugar de comparar la matriz de bytes)

Un mayor número de rondas no hace mucho más que ralentizar sería atacantes. Pero también es mucho más difícil reutilizar los hash en el futuro si pierde o necesita recrear su algoritmo hash. Puede consultar un hash de contraseña estándar como crypt en sistemas Unix. Esto le permite cambiar el algoritmo hash e incluso puede respaldar el control de versiones.

Pero, de nuevo, un simple hash + salt es lo suficientemente bueno para la mayoría de las aplicaciones.

Estrictamente más seguro:

Salt, HMAC, or both?

Ambos serían más seguros. Dado que la clave del HMAC podría considerarse una sal, hacer ambas cosas sería un poco redundante, pero aún más seguro, ya que tomaría más trabajo crackear.

How much salt?

Cada pedacito de sal duplicaría las combinaciones que necesitarían mantenerse en una tabla de arco iris para descifrar fácilmente la contraseña. Pero dado que solo hay una contraseña, y solo una sal, es posible que no se necesiten más. El HMAC usa el tamaño de bloque del hash subyacente para su tamaño de clave, 1024 bits para SHA512. El tamaño del bloque debería ser lo suficientemente bueno para la sal, pero doblarlo o triplicarlo haría mucho más difícil descifrar la contraseña con una tabla arcoíris.

How many iterations?

Mientras más, mejor. Claro, más iteraciones significa que tomará más tiempo determinar si se ingresó la contraseña correcta, pero las computadoras son rápidas y a los usuarios no les importará esperar unos segundos mientras verifican la contraseña. Hacer más iteraciones significaría que alguien que descifra la contraseña tendría que hacer más iteraciones también.

What encoding? (The password is plain ASCII)

También podría encriptar (con AES) la contraseña súper segura hiper-iterada, sobre-salada, HMAC, junto con su sal solo para hacerlo más difícil. Cree la contraseña para el hash y la clave de la contraseña cifrada, sea una combinación de cadenas que debe aparecer en el ejecutable, como “RNGCryptoServiceProvider” o “System.Security.Cryptography”. Y mientras codificamos, también podríamos convertirlo en hexadecimal o base64, o mejor aún en base 36 o alguna otra conversión menos esperada.

Nota: Esto fue escrito principalmente en broma, pero aún debe contener algo de verdad.

Creo que deberías apegarte a los estándares abiertos. Entre los esquemas hash actuales, el “{ssha}” utilizado por OpenLDAP es muy seguro y ampliamente utilizado. Puedes encontrar la descripción aquí,

http://www.openldap.org/faq/data/cache/347.html

La mayoría de las bibliotecas LDAP implementan este esquema.

Puede seguir un estándar publicado, como pkcs # 5. ver http://en.wikipedia.org/wiki/PKCS para una breve descripción, o http://tools.ietf.org/html/rfc2898 para el RFC.

Aquí hay una API que hará todo lo que necesite / desee 🙂

https://sourceforge.net/projects/pwdtknet