Supongo que la mejor manera de manejar las contraseñas para un sitio web es crear un hash de la contraseña y guardar ese hash en mi base de datos. Luego, cuando alguien intenta iniciar sesión, hago un hash de la contraseña que ingresaron y comparo.
¿Esto es correcto?
Y, ¿hay algún código de ejemplo que muestre cómo hacer esto en C #?
¿Y debo agregar un texto estándar a cada contraseña para que el texto que se está copiando tenga siempre al menos 20 caracteres?
Actualización: los otros enlaces no tienen código, así que esto es lo que implementé para esta pregunta. No incluyo el nombre de usuario porque eso puede cambiar, así que simplemente salt: contraseña. the: funciona porque uuencode no incluye un:.
public static class EncryptionUtilities
{
private const int SALT_SIZE = 8;
private const int NUM_ITERATIONS = 1000;
private static readonly RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
/// <summary>
/// Creates a signature for a password.
/// </summary>
/// <param name="password">The password to hash.</param>
/// <returns>the "salt:hash" for the password.</returns>
public static string CreatePasswordSalt(string password)
{
byte[] buf = new byte[SALT_SIZE];
rng.GetBytes(buf);
string salt = Convert.ToBase64String(buf);
Rfc2898DeriveBytes deriver2898 = new Rfc2898DeriveBytes(password.Trim(), buf, NUM_ITERATIONS);
string hash = Convert.ToBase64String(deriver2898.GetBytes(16));
return salt + ':' + hash;
}
/// <summary>
/// Validate if a password will generate the passed in salt:hash.
/// </summary>
/// <param name="password">The password to validate.</param>
/// <param name="saltHash">The "salt:hash" this password should generate.</param>
/// <returns>true if we have a match.</returns>
public static bool IsPasswordValid(string password, string saltHash)
{
string[] parts = saltHash.Split(new[] {':'}, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2)
return false;
byte[] buf = Convert.FromBase64String(parts[0]);
Rfc2898DeriveBytes deriver2898 = new Rfc2898DeriveBytes(password.Trim(), buf, NUM_ITERATIONS);
string computedHash = Convert.ToBase64String(deriver2898.GetBytes(16));
return parts[1].Equals(computedHash);
}
}
ps: consideré agregar "The World Wonders" al texto hash porque es la sal más famosa de todos los tiempos. Sin embargo, pensé que no añadía nada y el cifrado no es el lugar para introducir cadenas históricas.