Lo básico
El enfoque básico es Hash(secret | salt)
, que se almacena junto con la sal. Obviamente, es importante usar un algoritmo hash moderno como una de las variantes de SHA2 (aunque en la actualidad el SHA1 no está totalmente roto como lo está el MD5). Tenga en cuenta que si está almacenando preguntas de desafío de esta manera, probablemente desee Trim()
y ToLower()
el secreto antes de incluirlo. Esto puede reducir un poco la complejidad, pero las preguntas de seguridad no tienen la intención de tener una alta entropía como una contraseña.
¿Qué pasa con los ataques de fuerza bruta como las tablas Rainbow?
Las preocupaciones sobre los ataques de fuerza bruta se pueden mitigar de dos maneras:
- Requieren una cantidad mínima de entropía en el secreto (longitud, complejidad, etc.).
- Aumente la cantidad de cálculos necesarios para realizar el hash.
El método utilizado en bcrypt
es una buena mejora en el hashing estándar porque aumenta la cantidad de tiempo para calcular el hash en muchos órdenes de magnitud. Básicamente, simplemente separa el iterativamente el secreto muchas veces: Hash(Hash(...Hash(secret | salt)...))
Debido a que la cantidad de tiempo todavía es relativamente pequeña (cientos de milisegundos), no agrega un retraso intolerable al usuario legítimo. Pero puede arruinar los ataques automáticos de fuerza bruta.
Eso no es lo suficientemente bueno
Si la dificultad adicional de bcrypt
es insuficiente, intente scrypt
. Funciona como bcrypt
pero necesita guardar cada hash iterativo en la memoria para una fusión final al final. Esto agrega la misma complejidad de tiempo que bcrypt
, pero también aumenta la complejidad del espacio, lo que hace que sea más difícil de implementar en hardware, especialmente en paralelo.
Implementación
Honestamente, no conozco una biblioteca de C # para implementar esto, y mucho menos una "certificada" por algún organismo oficial, pero no sería demasiado difícil. Suponiendo que escriba código seguro para subprocesos y que la verificación de la contraseña se realice en un sistema confiable como un servidor, los problemas de implementación como ataques de canal lateral están minimizados.
Otras lecturas: Esta respuesta a ¿Es BCrypt un buen algoritmo de cifrado para usar en C #? ¿Dónde puedo encontrarlo?