with salted password hashed encrypt and c# security hash passwords windows-phone-7

c# - salted - salt password hash



Cómo hash una contraseña (4)

En base a csharptest.net''s excelente respuesta de csharptest.net''s , escribí una clase para esto:

public sealed class SecurePasswordHasher { /// <summary> /// Size of salt /// </summary> private const int SaltSize = 16; /// <summary> /// Size of hash /// </summary> private const int HashSize = 20; /// <summary> /// Creates a hash from a password /// </summary> /// <param name="password">the password</param> /// <param name="iterations">number of iterations</param> /// <returns>the hash</returns> public static string Hash(string password, int iterations) { //create salt byte[] salt; new RNGCryptoServiceProvider().GetBytes(salt = new byte[SaltSize]); //create hash var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations); var hash = pbkdf2.GetBytes(HashSize); //combine salt and hash var hashBytes = new byte[SaltSize + HashSize]; Array.Copy(salt, 0, hashBytes, 0, SaltSize); Array.Copy(hash, 0, hashBytes, SaltSize, HashSize); //convert to base64 var base64Hash = Convert.ToBase64String(hashBytes); //format hash with extra information return string.Format("$MYHASH$V1${0}${1}", iterations, base64Hash); } /// <summary> /// Creates a hash from a password with 10000 iterations /// </summary> /// <param name="password">the password</param> /// <returns>the hash</returns> public static string Hash(string password) { return Hash(password, 10000); } /// <summary> /// Check if hash is supported /// </summary> /// <param name="hashString">the hash</param> /// <returns>is supported?</returns> public static bool IsHashSupported(string hashString) { return hashString.Contains("$MYHASH$V1$"); } /// <summary> /// verify a password against a hash /// </summary> /// <param name="password">the password</param> /// <param name="hashedPassword">the hash</param> /// <returns>could be verified?</returns> public static bool Verify(string password, string hashedPassword) { //check hash if (!IsHashSupported(hashedPassword)) { throw new NotSupportedException("The hashtype is not supported"); } //extract iteration and Base64 string var splittedHashString = hashedPassword.Replace("$MYHASH$V1$", "").Split(''$''); var iterations = int.Parse(splittedHashString[0]); var base64Hash = splittedHashString[1]; //get hashbytes var hashBytes = Convert.FromBase64String(base64Hash); //get salt var salt = new byte[SaltSize]; Array.Copy(hashBytes, 0, salt, 0, SaltSize); //create hash with given salt var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations); byte[] hash = pbkdf2.GetBytes(HashSize); //get result for (var i = 0; i < HashSize; i++) { if (hashBytes[i + SaltSize] != hash[i]) { return false; } } return true; } }

Uso:

//Hash var hash = SecurePasswordHasher.Hash("mypassword"); //Verify var result = SecurePasswordHasher.Verify("mypassword", hash);

Un hash de muestra podría ser esto:

$MYHASH$V1$10000$Qhxzi6GNu/Lpy3iUqkeqR/J1hh8y/h5KPDjrv89KzfCVrubn

Como puede ver, también he incluido las iteraciones en el hash para facilitar el uso y la posibilidad de actualizarlo, si tenemos que actualizar.

hola, me gustaría almacenar el hash de una contraseña en el teléfono, pero no estoy seguro de cómo hacerlo. Parece que solo puedo encontrar métodos de encriptación. ¿Cuál es la mejor manera de hash la contraseña? Gracias


La mayoría de las otras respuestas aquí están algo desactualizadas con las mejores prácticas actuales. Como tal, aquí está la aplicación de usar PBKDF2 / Rfc2898DeriveBytes para almacenar y verificar contraseñas. El siguiente código está en una clase independiente en esta publicación: Otro ejemplo de cómo almacenar un hash de contraseña salada . Los conceptos básicos son realmente fáciles, así que aquí está desglosado:

PASO 1 Crea el valor de sal con un PRNG criptográfico:

byte[] salt; new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);

PASO 2 Crea el Rfc2898DeriveBytes y obtén el valor hash:

var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000); byte[] hash = pbkdf2.GetBytes(20);

PASO 3 Combine los bytes de sal y contraseña para usarlos posteriormente:

byte[] hashBytes = new byte[36]; Array.Copy(salt, 0, hashBytes, 0, 16); Array.Copy(hash, 0, hashBytes, 16, 20);

PASO 4 Gire la sal combinada + hash en una cadena para almacenamiento

string savedPasswordHash = Convert.ToBase64String(hashBytes); DBContext.AddUser(new User { ..., Password = savedPasswordHash });

PASO 5 Verificar la contraseña ingresada por el usuario contra una contraseña almacenada

/* Fetch the stored value */ string savedPasswordHash = DBContext.GetUser(u => u.UserName == user).Password; /* Extract the bytes */ byte[] hashBytes = Convert.FromBase64String(savedPasswordHash); /* Get the salt */ byte[] salt = new byte[16]; Array.Copy(hashBytes, 0, salt, 0, 16); /* Compute the hash on the password the user entered */ var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000); byte[] hash = pbkdf2.GetBytes(20); /* Compare the results */ for (int i=0; i < 20; i++) if (hashBytes[i+16] != hash[i]) throw new UnauthorizedAccessException();

Nota: Según los requisitos de rendimiento de su aplicación específica, se puede reducir el valor ''10000''. Un valor mínimo debería ser alrededor de 1000.


Utilizo un hash y una sal para el cifrado de mi contraseña (es el mismo hash que utiliza la Membresía Asp.Net):

private string PasswordSalt { get { var rng = new RNGCryptoServiceProvider(); var buff = new byte[32]; rng.GetBytes(buff); return Convert.ToBase64String(buff); } } private string EncodePassword(string password, string salt) { byte[] bytes = Encoding.Unicode.GetBytes(password); byte[] src = Encoding.Unicode.GetBytes(salt); byte[] dst = new byte[src.Length + bytes.Length]; Buffer.BlockCopy(src, 0, dst, 0, src.Length); Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length); HashAlgorithm algorithm = HashAlgorithm.Create("SHA1"); byte[] inarray = algorithm.ComputeHash(dst); return Convert.ToBase64String(inarray); }


ACTUALIZACIÓN : ESTA RESPUESTA ESTÁ SERIAMENTE DESPLAZADA . Utilice las recomendaciones de https://.com/a/10402129/251311 lugar.

Puedes usar

var md5 = new MD5CryptoServiceProvider(); var md5data = md5.ComputeHash(data);

o

var sha1 = new SHA1CryptoServiceProvider(); var sha1data = sha1.ComputeHash(data);

Para obtener data como matriz de bytes, puede usar

var data = Encoding.ASCII.GetBytes(password);

y para recuperar cadenas de md5data o sha1data

var hashedPassword = ASCIIEncoding.GetString(md5data);