Mots de passe Hash et Salt en C #

178

J'étais en train de parcourir l'un des articles de DavidHayden sur le hachage des mots de passe utilisateur .

Vraiment, je ne peux pas obtenir ce qu'il essaie de réaliser.

Voici son code:

private static string CreateSalt(int size)
{
    //Generate a cryptographic random number.
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    byte[] buff = new byte[size];
    rng.GetBytes(buff);

    // Return a Base64 string representation of the random number.
    return Convert.ToBase64String(buff);
}

private static string CreatePasswordHash(string pwd, string salt)
{
    string saltAndPwd = String.Concat(pwd, salt);
    string hashedPwd =
        FormsAuthentication.HashPasswordForStoringInConfigFile(
        saltAndPwd, "sha1");
    return hashedPwd;
}

Existe-t-il une autre méthode C # pour hacher les mots de passe et y ajouter du sel?

ACP
la source
voici une bibliothèque qui fait le hachage avec du sel encrypto.codeplex.com
Omu
6
Que devez-vous transmettre pour la taille dans la première méthode pour générer du sel?
Shane LeBlanc
6
Le lien est rompu.
osmanraifgunes
@ShaneLeBlanc Vous devez au moins autant de bits que la fonction possède des sorties. SHA1n'est pas de qualité cryptographique, vous devriez donc au moins utiliser SHA256, qui produit 256 bits ou 32 octets. MAIS, 256 bits n'est PAS facilement convertible en base 64, car chaque caractère en base64 code 6 bits et 256 n'est pas entièrement divisible par 6. Vous avez donc besoin d'un dénominateur commun de 6 (pour base64) et 8 (pour les bits dans un octet) sur 256 bits, soit 264 bits ou 33 octets. TLDR: Utilisez 33.
VSO

Réponses:

248

En fait, c'est un peu étrange, avec les conversions de chaînes - que le fournisseur d'appartenance fait pour les mettre dans des fichiers de configuration. Les hachages et les sels sont des blobs binaires, vous n'avez pas besoin de les convertir en chaînes à moins que vous ne souhaitiez les mettre dans des fichiers texte.

Dans mon livre, Beginning ASP.NET Security , (oh enfin, une excuse pour soutirer le livre) je fais ce qui suit

static byte[] GenerateSaltedHash(byte[] plainText, byte[] salt)
{
  HashAlgorithm algorithm = new SHA256Managed();

  byte[] plainTextWithSaltBytes = 
    new byte[plainText.Length + salt.Length];

  for (int i = 0; i < plainText.Length; i++)
  {
    plainTextWithSaltBytes[i] = plainText[i];
  }
  for (int i = 0; i < salt.Length; i++)
  {
    plainTextWithSaltBytes[plainText.Length + i] = salt[i];
  }

  return algorithm.ComputeHash(plainTextWithSaltBytes);            
}

La génération de sel est l'exemple de la question. Vous pouvez convertir du texte en tableaux d'octets en utilisant Encoding.UTF8.GetBytes(string). Si vous devez convertir un hachage en sa représentation sous forme de chaîne, vous pouvez utiliser Convert.ToBase64StringetConvert.FromBase64String le reconvertir.

Vous devez noter que vous ne pouvez pas utiliser l'opérateur d'égalité sur les tableaux d'octets, il vérifie les références et vous devez donc simplement parcourir les deux tableaux en vérifiant chaque octet ainsi

public static bool CompareByteArrays(byte[] array1, byte[] array2)
{
  if (array1.Length != array2.Length)
  {
    return false;
  }

  for (int i = 0; i < array1.Length; i++)
  {
    if (array1[i] != array2[i])
    {
      return false;
    }
  }

  return true;
}

Utilisez toujours un nouveau sel par mot de passe. Les sels ne doivent pas être tenus secrets et peuvent être stockés avec le hachage lui-même.

blowdart
la source
3
Merci pour ce conseil - m'a vraiment aidé à démarrer. Je suis également tombé sur ce lien < dijksterhuis.org/creating-salted-hash-values-in-c > que j'ai trouvé était de bons conseils pratiques et reflète une grande partie de ce qui a été dit dans cet article
Alex P
18
Refactor de déclaration LINQ astucieux pour CompareByteArrays return array1.Length == array2.Length && !array1.Where((t, i) => t != array2[i]).Any();
chasseur
6
@Brettski Techniquement, oui, mais avoir un sel unique pour chaque utilisateur rend Rainbow Tables (généralement accepté comme le moyen le plus efficace de déchiffrer des mots de passe hachés) pratiquement inutile. Ceci est un aperçu rapide qui donne un aperçu détaillé mais pas écrasant de la façon de stocker les mots de passe en toute sécurité, et pourquoi / comment tout cela fonctionne.
Ranger
3
@hunter: vous devez ajouter un .ToList () pour le rendre constant. par exemple: return array1.Length == array2.Length &&! array1.Where ((t, i) => t! = array2 [i]). ToList (). Any (); Sinon, LINQ reviendra dès qu'il trouvera un octet qui n'est pas égal.
Alex Rouillard
17
-1 pour utiliser une fonction de hachage rapide. Utilisez une construction lente comme PBKDF2, bcrypt ou scrypt.
CodesInChaos
48

Qu'est-ce que Blowdart a dit, mais avec un peu moins de code. Utilisez Linq ou CopyTopour concaténer des tableaux.

public static byte[] Hash(string value, byte[] salt)
{
    return Hash(Encoding.UTF8.GetBytes(value), salt);
}

public static byte[] Hash(byte[] value, byte[] salt)
{
    byte[] saltedValue = value.Concat(salt).ToArray();
    // Alternatively use CopyTo.
    //var saltedValue = new byte[value.Length + salt.Length];
    //value.CopyTo(saltedValue, 0);
    //salt.CopyTo(saltedValue, value.Length);

    return new SHA256Managed().ComputeHash(saltedValue);
}

Linq a également un moyen facile de comparer vos tableaux d'octets.

public bool ConfirmPassword(string password)
{
    byte[] passwordHash = Hash(password, _passwordSalt);

    return _passwordHash.SequenceEqual(passwordHash);
}

Avant de mettre en œuvre tout cela, consultez cet article . Pour le hachage de mot de passe, vous voudrez peut-être un algorithme de hachage lent, pas rapide.

À cette fin, il y a la Rfc2898DeriveBytesclasse qui est lente (et peut être ralentie), et peut répondre à la deuxième partie de la question originale en ce qu'elle peut prendre un mot de passe et du sel et renvoyer un hachage. Consultez cette question pour plus d'informations. Remarque: Stack Exchange utiliseRfc2898DeriveBytes pour le hachage de mot de passe (code source ici ).

Adam Boddington
la source
6
@MushinNoShin SHA256 est un hachage rapide. Le hachage de mot de passe nécessite un hachage lent, comme PBKDF2, bcrypt ou scrypt. Voir Comment hacher en toute sécurité les mots de passe? sur security.se pour plus de détails.
CodesInChaos du
32

J'ai lu que les fonctions de hachage comme SHA256 n'étaient pas vraiment destinées à être utilisées avec le stockage des mots de passe: https://patrickmn.com/security/storing-passwords-securely/#notpasswordhashes

Au lieu de cela, les fonctions de dérivation de clé adaptative telles que PBKDF2, bcrypt ou scrypt l'étaient. En voici un basé sur PBKDF2 que Microsoft a écrit pour PasswordHasher dans leur bibliothèque Microsoft.AspNet.Identity:

/* =======================
 * HASHED PASSWORD FORMATS
 * =======================
 * 
 * Version 3:
 * PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations.
 * Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
 * (All UInt32s are stored big-endian.)
 */

public string HashPassword(string password)
{
    var prf = KeyDerivationPrf.HMACSHA256;
    var rng = RandomNumberGenerator.Create();
    const int iterCount = 10000;
    const int saltSize = 128 / 8;
    const int numBytesRequested = 256 / 8;

    // Produce a version 3 (see comment above) text hash.
    var salt = new byte[saltSize];
    rng.GetBytes(salt);
    var subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);

    var outputBytes = new byte[13 + salt.Length + subkey.Length];
    outputBytes[0] = 0x01; // format marker
    WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
    WriteNetworkByteOrder(outputBytes, 5, iterCount);
    WriteNetworkByteOrder(outputBytes, 9, saltSize);
    Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
    Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
    return Convert.ToBase64String(outputBytes);
}

public bool VerifyHashedPassword(string hashedPassword, string providedPassword)
{
    var decodedHashedPassword = Convert.FromBase64String(hashedPassword);

    // Wrong version
    if (decodedHashedPassword[0] != 0x01)
        return false;

    // Read header information
    var prf = (KeyDerivationPrf)ReadNetworkByteOrder(decodedHashedPassword, 1);
    var iterCount = (int)ReadNetworkByteOrder(decodedHashedPassword, 5);
    var saltLength = (int)ReadNetworkByteOrder(decodedHashedPassword, 9);

    // Read the salt: must be >= 128 bits
    if (saltLength < 128 / 8)
    {
        return false;
    }
    var salt = new byte[saltLength];
    Buffer.BlockCopy(decodedHashedPassword, 13, salt, 0, salt.Length);

    // Read the subkey (the rest of the payload): must be >= 128 bits
    var subkeyLength = decodedHashedPassword.Length - 13 - salt.Length;
    if (subkeyLength < 128 / 8)
    {
        return false;
    }
    var expectedSubkey = new byte[subkeyLength];
    Buffer.BlockCopy(decodedHashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);

    // Hash the incoming password and verify it
    var actualSubkey = KeyDerivation.Pbkdf2(providedPassword, salt, prf, iterCount, subkeyLength);
    return actualSubkey.SequenceEqual(expectedSubkey);
}

private static void WriteNetworkByteOrder(byte[] buffer, int offset, uint value)
{
    buffer[offset + 0] = (byte)(value >> 24);
    buffer[offset + 1] = (byte)(value >> 16);
    buffer[offset + 2] = (byte)(value >> 8);
    buffer[offset + 3] = (byte)(value >> 0);
}

private static uint ReadNetworkByteOrder(byte[] buffer, int offset)
{
    return ((uint)(buffer[offset + 0]) << 24)
        | ((uint)(buffer[offset + 1]) << 16)
        | ((uint)(buffer[offset + 2]) << 8)
        | ((uint)(buffer[offset + 3]));
}

Notez que cela nécessite l' installation du package nuget Microsoft.AspNetCore.Cryptography.KeyDerivation qui nécessite .NET Standard 2.0 (.NET 4.6.1 ou supérieur). Pour les versions antérieures de .NET, consultez la classe Crypto de la bibliothèque System.Web.Helpers de Microsoft.

Mise à jour novembre 2015
Réponse mise à jour pour utiliser une implémentation d'une autre bibliothèque Microsoft qui utilise le hachage PBKDF2-HMAC-SHA256 au lieu de PBKDF2-HMAC-SHA1 (notez que PBKDF2-HMAC-SHA1 est toujours sécurisé si iterCount est suffisamment élevé). Vous pouvez consulter la source à partir de laquelle le code simplifié a été copié car il gère en fait la validation et la mise à niveau des hachages implémentés à partir de la réponse précédente, utile si vous devez augmenter iterCount à l'avenir.

Michael
la source
1
Notez qu'il vaut peut-être la peine d'augmenter PBKDF2IterCount à un nombre plus élevé, voir security.stackexchange.com/q/3959 pour plus d'informations.
Michael
2
1) Réduisez PBKDF2SubkeyLengthà 20 octets. C'est la taille naturelle f SHA1 et l'augmenter au-delà de cela ralentit le défenseur sans ralentir l'attaquant. 2) Je recommande d'augmenter le nombre d'itérations. Je recommande 10k à 100k en fonction de votre budget de performance. 3) Une comparaison à temps constant ne ferait pas de mal non plus, mais n'a pas beaucoup d'impact pratique.
CodesInChaos
KeyDerivationPrf, KeyDerivation et BlockCopy ne sont pas définis, quelles sont leurs classes?
mrbengi
@mrbengi Avez-vous installé le package nuget Microsoft.AspNet.Cryptography.KeyDerivation mentionné? Si cela ne convient pas, voici une version qui ne nécessite pas le package nuget. Buffer.BlockCopy doit exister, il fait partie de System.
Michael
1
Le package nuget s'appelle désormais Microsoft.AspNetCore.Cryptography.KeyDerivation.
James Blake
25

Le sel est utilisé pour ajouter un niveau supplémentaire de complexité au hachage, pour rendre plus difficile la fissuration par force brute.

Extrait d'un article sur Sitepoint :

Un pirate informatique peut toujours effectuer ce qu'on appelle une attaque par dictionnaire. Des parties malveillantes peuvent effectuer une attaque par dictionnaire en prenant, par exemple, 100000 mots de passe qu'ils savent que les gens utilisent fréquemment (par exemple, noms de villes, équipes sportives, etc.), les hacher, puis comparer chaque entrée du dictionnaire à chaque ligne de la base de données. table. Si les hackers trouvent une correspondance, bingo! Ils ont votre mot de passe. Pour résoudre ce problème, cependant, nous n'avons besoin que de sel de hachage.

Pour saler un hachage, nous proposons simplement une chaîne de texte à l'aspect aléatoire, la concaténons avec le mot de passe fourni par l'utilisateur, puis hachons ensemble la chaîne et le mot de passe générés de manière aléatoire en une seule valeur. Nous enregistrons ensuite le hachage et le sel dans des champs séparés dans la table Users.

Dans ce scénario, non seulement un hacker aurait besoin de deviner le mot de passe, mais il devrait également deviner le sel. Ajouter du sel au texte clair améliore la sécurité: maintenant, si un pirate tente une attaque par dictionnaire, il doit hacher ses 100 000 entrées avec le sel de chaque ligne utilisateur. Bien que ce soit toujours possible, les chances de succès du piratage diminuent radicalement.

Il n'y a pas de méthode pour faire cela automatiquement dans .NET, vous devrez donc utiliser la solution ci-dessus.

Seb Nilsson
la source
Les sels sont utilisés pour se défendre contre des choses comme les tables arc-en-ciel. Pour se défendre contre les attaques par dictionnaire, un facteur de travail (également connu sous le nom d'étirement de clé) est requis comme tout bon KDF: en.wikipedia.org/wiki/Key_stretching
Erwan Legrand
11

J'ai créé une classe qui a la méthode suivante:

  1. Créer du sel
  2. Entrée de hachage
  3. Valider l'entrée

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

    »

Bamidele Alegbe
la source
3

J'ai créé une bibliothèque SimpleHashing.Net pour faciliter le processus de hachage avec les classes de base fournies par Microsoft. Un SHA ordinaire ne suffit plus vraiment pour que les mots de passe soient stockés en toute sécurité.

La bibliothèque utilise l'idée du format de hachage de Bcrypt, mais comme il n'y a pas d'implémentation officielle de MS, je préfère utiliser ce qui est disponible dans le framework (c'est-à-dire PBKDF2), mais c'est un peu trop difficile hors de la boîte.

Voici un exemple rapide d'utilisation de la bibliothèque:

ISimpleHash simpleHash = new SimpleHash();

// Creating a user hash, hashedPassword can be stored in a database
// hashedPassword contains the number of iterations and salt inside it similar to bcrypt format
string hashedPassword = simpleHash.Compute("Password123");

// Validating user's password by first loading it from database by username
string storedHash = _repository.GetUserPasswordHash(username);
isPasswordValid = simpleHash.Verify("Password123", storedHash);
Ilya Chernomordik
la source
2

Voici comment je fais. Je crée le hachage et le stocke à l'aide de l' ProtectedDataAPI:

    public static string GenerateKeyHash(string Password)
    {
        if (string.IsNullOrEmpty(Password)) return null;
        if (Password.Length < 1) return null;

        byte[] salt = new byte[20];
        byte[] key = new byte[20];
        byte[] ret = new byte[40];

        try
        {
            using (RNGCryptoServiceProvider randomBytes = new RNGCryptoServiceProvider())
            {
                randomBytes.GetBytes(salt);

                using (var hashBytes = new Rfc2898DeriveBytes(Password, salt, 10000))
                {
                    key = hashBytes.GetBytes(20);
                    Buffer.BlockCopy(salt, 0, ret, 0, 20);
                    Buffer.BlockCopy(key, 0, ret, 20, 20);
                }
            }
            // returns salt/key pair
            return Convert.ToBase64String(ret);
        }
        finally
        {
            if (salt != null)
                Array.Clear(salt, 0, salt.Length);
            if (key != null)
                Array.Clear(key, 0, key.Length);
            if (ret != null)
                Array.Clear(ret, 0, ret.Length);
        } 
    }

    public static bool ComparePasswords(string PasswordHash, string Password)
    {
        if (string.IsNullOrEmpty(PasswordHash) || string.IsNullOrEmpty(Password)) return false;
        if (PasswordHash.Length < 40 || Password.Length < 1) return false;

        byte[] salt = new byte[20];
        byte[] key = new byte[20];
        byte[] hash = Convert.FromBase64String(PasswordHash);

        try
        {
            Buffer.BlockCopy(hash, 0, salt, 0, 20);
            Buffer.BlockCopy(hash, 20, key, 0, 20);

            using (var hashBytes = new Rfc2898DeriveBytes(Password, salt, 10000))
            {
                byte[] newKey = hashBytes.GetBytes(20);

                if (newKey != null)
                    if (newKey.SequenceEqual(key))
                        return true;
            }
            return false;
        }
        finally
        {
            if (salt != null)
                Array.Clear(salt, 0, salt.Length);
            if (key != null)
                Array.Clear(key, 0, key.Length);
            if (hash != null)
                Array.Clear(hash, 0, hash.Length);
        }
    }

    public static byte[] DecryptData(string Data, byte[] Salt)
    {
        if (string.IsNullOrEmpty(Data)) return null;

        byte[] btData = Convert.FromBase64String(Data);

        try
        {
            return ProtectedData.Unprotect(btData, Salt, DataProtectionScope.CurrentUser);
        }
        finally
        {
            if (btData != null)
                Array.Clear(btData, 0, btData.Length);
        }
    }

    public static string EncryptData(byte[] Data, byte[] Salt)
    {
        if (Data == null) return null;
        if (Data.Length < 1) return null;

        byte[] buffer = new byte[Data.Length];

        try
        {
            Buffer.BlockCopy(Data, 0, buffer, 0, Data.Length);
            return System.Convert.ToBase64String(ProtectedData.Protect(buffer, Salt, DataProtectionScope.CurrentUser));
        }
        finally
        {
            if (buffer != null)
                Array.Clear(buffer, 0, buffer.Length);
        }
    }
JGU
la source
Comment l'appeler en économisant et en comparant plus tard?
SearchForKnowledge
2

J'ai lu toutes les réponses et je pense que celles-ci suffisent, spécialement les articles @Michael avec hachage lent et @CodesInChaos de bons commentaires, mais j'ai décidé de partager mon extrait de code pour le hachage / validation qui peut être utile et ne nécessite pas [ Microsoft.AspNet.Cryptography .KeyDerivation ].

    private static bool SlowEquals(byte[] a, byte[] b)
            {
                uint diff = (uint)a.Length ^ (uint)b.Length;
                for (int i = 0; i < a.Length && i < b.Length; i++)
                    diff |= (uint)(a[i] ^ b[i]);
                return diff == 0;
            }

    private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
            {
                Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt);
                pbkdf2.IterationCount = iterations;
                return pbkdf2.GetBytes(outputBytes);
            }

    private static string CreateHash(string value, int salt_bytes, int hash_bytes, int pbkdf2_iterations)
            {
                // Generate a random salt
                RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
                byte[] salt = new byte[salt_bytes];
                csprng.GetBytes(salt);

                // Hash the value and encode the parameters
                byte[] hash = PBKDF2(value, salt, pbkdf2_iterations, hash_bytes);

                //You need to return the salt value too for the validation process
                return Convert.ToBase64String(hash) + ":" + 
                       Convert.ToBase64String(hash);
            }

    private static bool ValidateHash(string pureVal, string saltVal, string hashVal, int pbkdf2_iterations)
            {
                try
                {
                    byte[] salt = Convert.FromBase64String(saltVal);
                    byte[] hash = Convert.FromBase64String(hashVal);

                    byte[] testHash = PBKDF2(pureVal, salt, pbkdf2_iterations, hash.Length);
                    return SlowEquals(hash, testHash);
                }
                catch (Exception ex)
                {
                    return false;
                }
            }

Veuillez prêter attention à la fonction SlowEquals qui est si importante, Enfin, j'espère que cette aide et n'hésitez pas à me conseiller sur de meilleures approches.

QMaster
la source
Plutôt que de créer une boucle occupée, pourquoi ne pas mettre dans un délai artificiel non occupé. par exemple en utilisant Task.Delay. Cela retardera une tentative de force brute mais ne bloquera pas le thread actif.
gburton
@gburton Merci pour vos conseils. Je vais vérifier.
QMaster
Il y a une faute de frappe dans CreateHash: vous concantez Convert.ToBase64String (hachage) à lui-même au lieu du salt. À part cela, c'est une bonne réponse qui répond à peu près à tous les problèmes soulevés dans les commentaires sur d'autres réponses.
ZeRemz
2

Utilisez le System.Web.Helpers.Cryptopackage NuGet de Microsoft. Il ajoute automatiquement du sel au hachage.

Vous hachez un mot de passe comme celui-ci: var hash = Crypto.HashPassword("foo");

Vous vérifiez un mot de passe comme celui-ci: var verified = Crypto.VerifyHashedPassword(hash, "foo");

Kai Hartmann
la source
1

Si vous n'utilisez pas asp.net ou .net core, il y a aussi un moyen simple dans les projets> = .Net Standard 2.0.

Tout d'abord, vous pouvez définir la taille souhaitée du hachage, du sel et du numéro d'itération qui est lié à la durée de la génération du hachage:

private const int SaltSize = 32;
private const int HashSize = 32;
private const int IterationCount = 10000;

Pour générer le hachage et le sel du mot de passe, vous pouvez utiliser quelque chose comme ceci:

public static string GeneratePasswordHash(string password, out string salt)
{
    using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
    {
        rfc2898DeriveBytes.IterationCount = IterationCount;
        byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
        byte[] saltData = rfc2898DeriveBytes.Salt;
        salt = Convert.ToBase64String(saltData);
        return Convert.ToBase64String(hashData);
    }
}

Pour vérifier si le mot de passe entré par l'utilisateur est valide, vous pouvez vérifier avec les valeurs de votre base de données:

public static bool VerifyPassword(string password, string passwordHash, string salt)
{
    using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
    {
        rfc2898DeriveBytes.IterationCount = IterationCount;
        rfc2898DeriveBytes.Salt = Convert.FromBase64String(salt);
        byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
        return Convert.ToBase64String(hashData) == passwordHash;
    }
}

Le test unitaire suivant montre l'utilisation:

string password = "MySecret";

string passwordHash = PasswordHasher.GeneratePasswordHash(password, out string salt);

Assert.True(PasswordHasher.VerifyPassword(password, passwordHash, salt));
Assert.False(PasswordHasher.VerifyPassword(password.ToUpper(), passwordHash, salt));

Source Microsoft Rfc2898DeriveBytes

Eugstman
la source
-1

En réponse à cette partie de la question d'origine "Existe-t-il une autre méthode C # pour le hachage des mots de passe" Vous pouvez y parvenir en utilisant ASP.NET Identity v3.0 https://www.nuget.org/packages/Microsoft.AspNet.Identity. EntityFramework / 3.0.0-rc1-final

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using System.Security.Principal;

namespace HashTest{


    class Program
    {
        static void Main(string[] args)
        {

            WindowsIdentity wi = WindowsIdentity.GetCurrent();

            var ph = new PasswordHasher<WindowsIdentity>();

            Console.WriteLine(ph.HashPassword(wi,"test"));

            Console.WriteLine(ph.VerifyHashedPassword(wi,"AQAAAAEAACcQAAAAEA5S5X7dmbx/NzTk6ixCX+bi8zbKqBUjBhID3Dg1teh+TRZMkAy3CZC5yIfbLqwk2A==","test"));

        }
    }


}
Dave Cornall
la source
-1
 protected void m_GenerateSHA256_Button1_Click(objectSender, EventArgs e)
{
string salt =createSalt(10);
string hashedPassword=GenerateSHA256Hash(m_UserInput_TextBox.Text,Salt);
m_SaltHash_TextBox.Text=Salt;
 m_SaltSHA256Hash_TextBox.Text=hashedPassword;

}
 public string createSalt(int size)
{
 var rng= new System.Security.Cyptography.RNGCyptoServiceProvider();
 var buff= new byte[size];
rng.GetBytes(buff);
 return Convert.ToBase64String(buff);
}


 public string GenerateSHA256Hash(string input,string salt)
{
 byte[]bytes=System.Text.Encoding.UTF8.GetBytes(input+salt);
 new System.Security.Cyptography.SHA256Managed();
 byte[]hash=sha256hashString.ComputedHash(bytes);
 return bytesArrayToHexString(hash);
  }
Ankush shukla
la source
l'autre méthode est la chaîne password = HashPasswordForStoringInConfigFile (TextBox1.Text, SHA1)
ankush shukla
-6
create proc [dbo].[hash_pass] @family nvarchar(50), @username nvarchar(50), @pass nvarchar(Max),``` @semat nvarchar(50), @tell nvarchar(50)

as insert into tbl_karbar values (@family,@username,(select HASHBYTES('SHA1' ,@pass)),@semat,@tell)
ehsan
la source