web-dev-qa-db-fra.com

Comment hacher un mot de passe

hé, j'aimerais stocker le hash d'un mot de passe sur le téléphone, mais je ne sais pas comment le faire. Je ne peux que sembler trouver des méthodes de cryptage. Quelle est la meilleure façon de hacher le mot de passe? Merci

106
Skoder

[~ # ~] mettre à jour [~ # ~] : CETTE RÉPONSE IS = SERIEUSEMENT DEPASSE . Veuillez utiliser les recommandations du https://stackoverflow.com/a/10402129/251311 .

Vous pouvez soit utiliser

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

ou

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

Pour obtenir data sous forme de tableau d'octets, vous pouvez utiliser

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

et pour récupérer la chaîne de md5data ou sha1data

var hashedPassword = ASCIIEncoding.GetString(md5data);
54
zerkms

La plupart des autres réponses ici sont quelque peu dépassées par les meilleures pratiques actuelles. En tant que tel, voici l'utilisation de PBKDF2/Rfc2898DeriveBytes pour stocker et vérifier les mots de passe. Le code suivant est dans une classe autonome dans ce post: n autre exemple de la façon de stocker un hachage de mot de passe salé . Les bases sont vraiment faciles, alors voici les détails:

ÉTAPE 1 Créez la valeur du sel avec un PRNG cryptographique:

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

ÉTAPE 2 Créez le Rfc2898DeriveBytes et obtenez la valeur de hachage:

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

ÉTAPE 3 Combinez les octets salt et password pour une utilisation ultérieure:

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

ÉTAPE 4 Tournez le sel + hachage combiné en une chaîne pour le stockage

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

ÉTAPE 5 Vérifiez le mot de passe saisi par l'utilisateur par rapport à un mot de passe stocké.

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

Remarque: en fonction des exigences de performance de votre application spécifique, la valeur "10000" peut être réduite. Une valeur minimale devrait être autour de 1000.

259
csharptest.net

Sur la base de csharptest.net's excellente réponse, j'ai écrit un cours pour cela:

public static 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>
    /// Checks 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>
    /// Verifies 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 hash bytes
        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;
    }
}

Usage:

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

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

Un exemple de hash pourrait être ceci:

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

Comme vous pouvez le constater, j’ai également inclus les itérations dans le hachage pour une utilisation facile et la possibilité de les mettre à niveau, si nous avons besoin de les mettre à jour.


Si vous êtes intéressé par .net core, j'ai aussi une version .net core sur Code Review .

58
Christian Gollhardt

J'utilise un hachage et un sel pour le cryptage de mon mot de passe (c'est le même hachage que celui utilisé par les membres 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);
}
13
Martin
  1. Créer un sel,
  2. Créer un mot de passe de hachage avec du sel
  3. Sauver le hasch et le sel
  4. déchiffrer avec mot de passe et sel ... pour que les développeurs ne puissent pas déchiffrer le mot de passe
public class CryptographyProcessor
{
    public string CreateSalt(int size)
    {
        //Generate a cryptographic random number.
          RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
         byte[] buff = new byte[size];
         rng.GetBytes(buff);
         return Convert.ToBase64String(buff);
    }


      public string GenerateHash(string input, string salt)
      { 
         byte[] bytes = Encoding.UTF8.GetBytes(input + salt);
         SHA256Managed sHA256ManagedString = new SHA256Managed();
         byte[] hash = sHA256ManagedString.ComputeHash(bytes);
         return Convert.ToBase64String(hash);
      }

      public bool AreEqual(string plainTextInput, string hashedInput, string salt)
      {
           string newHashedPin = GenerateHash(plainTextInput, salt);
           return newHashedPin.Equals(hashedInput); 
      }
 }
0
Bamidele Alegbe