Actualmente estamos trabajando en una nueva aplicación de servidor que se comunicará con las aplicaciones cliente en muchos sistemas diferentes. Para esto queríamos implementar un nuevo esquema de hashing de contraseña.
He investigado bastante, incluida la lectura de muchas preguntas sobre seguridad.SE y crypto.SE, sobre el hashing de las contraseñas. Después de esta investigación, he encontrado el siguiente esquema de hash:
Usaremos PBKDF2
como algoritmo de hashing. La elección para esto radica principalmente en que esté disponible directamente en .NET Framework. He analizado tanto bcrypt
como scrypt
, pero como ambos necesitan bibliotecas de terceros, solo hemos ido con PBKDF2
.
Con el uso de PBKDF2
también está la sal libre que se obtiene al generar un hash por primera vez.
La pregunta entonces era cómo guardar los datos en la base de datos. Teníamos dos opciones:
- Guarde cada valor por separado, es decir, hash, sal, iteraciones y algoritmo.
- O guárdelo como una sola cadena.
Fuimos con el valor de cadena única que se ve de la siguiente manera:
<algorithm>$<iterations>$<salt>$<hash>
Esto es similar a cómo, por ejemplo, Django lo hace.
Lo implementé así y escribí un informe con nuestras elecciones y argumentos. Pero ahora me sale preguntas sobre el diseño. Por ejemplo, algunos se preguntan por qué la sal se guarda tan claramente, ¿no sería mejor combinar la sal y el hash en una sola cadena para que sea menos evidente para los atacantes?
Por lo general, estos casos hacen suposiciones donde los atacantes solo tienen la base de datos y tal. Si bien afirmo que siempre debemos mirar el peor de los casos y asumir que los atacantes tienen tanto el código como la base de datos. También afirmo que la sal está ahí para negar el efecto de las tablas de arco iris y las tablas de búsqueda. Y el número de iteraciones es el de los ataques de fuerza bruta.
Pero como no soy un profesional de la seguridad, lo que digo puede ignorarse fácilmente (aunque esto se aplica a cualquier argumento en Internet;)).
Por lo tanto, necesito algo que pueda mostrar que lo que creamos es una forma correcta de hacerlo.
Acabo de implementar muchas cosas que encontré en Internet, pero no tengo pruebas (científicas) de que esto sea suficiente.