Jak hashować hasło

Hej, Chciałbym zapisać hash hasła w telefonie, ale nie jestem pewien, jak to zrobić. Mogę tylko znaleźć metody szyfrowania. Jaki jest najlepszy sposób na hashowanie hasła? dzięki

Author: Skoder, 2010-11-15

4 answers

AKTUALIZACJA: TA ODPOWIEDŹ JEST POWAŻNIE PRZESTARZAŁA . Proszę skorzystać z zaleceń z https://stackoverflow.com/a/10402129/251311 zamiast tego.

Możesz użyć

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

Lub

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

Aby uzyskać data jako tablicę bajtów można użyć

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

I aby odzyskać ciąg z md5data lub sha1data

var hashedPassword = ASCIIEncoding.GetString(md5data);
 42
Author: zerkms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:33

Większość innych odpowiedzi tutaj są nieco nieaktualne z dzisiejszych najlepszych praktyk. Jako takie tutaj jest zastosowanie za pomocą PBKDF2 / Rfc2898DeriveBytes do przechowywania i weryfikacji haseł. Poniższy kod znajduje się w samodzielnej klasie w tym poście: kolejny przykład jak zapisać hash hasła . Podstawy są naprawdę proste, więc tutaj jest to rozbite:

Krok 1 Utwórz wartość salt za pomocą kryptograficznego PRNG:

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

Krok 2 Utwórz Rfc2898DeriveBytes i uzyskać wartość hash:

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

Krok 3 Połącz bajty soli i hasła do późniejszego użycia:

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

KROK 4 Przekształć połączoną sól+hash w łańcuch do przechowywania

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

Krok 5 zweryfikuj hasło wprowadzone przez użytkownika z zapisanym hasłem

/* 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();

Uwaga: w zależności od wymagań wydajnościowych konkretnego zastosowania, wartość "10000" może zostać zmniejszona. Minimalna wartość powinna wynosić około 1000.

 206
Author: csharptest.net,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-01 18:12:24

Na podstawie csharptest.net ' S świetna odpowiedź, napisałem do tego klasę:

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;
    }
}

Użycie:

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

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

Przykładowy hash może być taki:

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

Jak widzisz, dodałem również iteracje w hash dla łatwego użycia i możliwość uaktualnienia tego, jeśli trzeba uaktualnić.

 41
Author: Christian Gollhardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:26

Używam hash i salt do szyfrowania hasła (jest to ten sam hash, który Asp.Net "Member uses"): {]}

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);
}
 13
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-12 18:09:20