J'ai lu que les fonctions de hachage comme SHA256 n'étaient pas vraiment destinées à être utilisées pour stocker des mots de passe : https://patrickmn.com/security/storing-passwords-securely/#notpasswordhashes
Au lieu de cela, des fonctions de dérivation de clés adaptatives comme PBKDF2, bcrypt ou scrypt ont été utilisées. Voici une fonction basée 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 Microsoft.AspNetCore.Cryptography.KeyDerivation paquet nuget installé qui nécessite .NET Standard 2.0 (.NET 4.6.1 ou supérieur). Pour les versions antérieures de .NET, voir le Crypto de la bibliothèque System.Web.Helpers de Microsoft.
Mise à jour Nov 2015
Mise à jour de la réponse pour utiliser une implémentation d'une bibliothèque Microsoft différente qui utilise le hachage PBKDF2-HMAC-SHA256 au lieu de PBKDF2-HMAC-SHA1 (notez que PBKDF2-HMAC-SHA1 est toujours en sécurité si iterCount est suffisamment élevé). Vous pouvez consulter le source le code simplifié a été copié à partir de car il gère effectivement la validation et la mise à jour des hachages implémentés à partir de la réponse précédente, utile si vous avez besoin d'augmenter iterCount dans le futur.
1 votes
Voici une bibliothèque qui effectue le hachage avec du sel encrypto.codeplex.com
6 votes
Que devez-vous passer pour la taille dans la première méthode pour générer du sel ?
9 votes
Le lien est rompu.
0 votes
@ShaneLeBlanc Vous devriez avoir au moins autant de bits que de sorties de fonctions.
SHA1
n'est pas cryptographique, vous devriez donc au moins utiliserSHA256
ce qui donne 256 bits ou 32 octets. MAIS, 256 bits ne sont PAS facilement convertibles en base 64, car chaque caractère en base 64 encode 6 bits, et 256 n'est pas divisible entièrement par 6. Vous avez donc besoin d'un dénominateur commun de 6 (pour la base 64) et 8 (pour les bits dans un octet) sur 256 bits, soit 264 bits ou 33 octets. TLDR : Utilisez 33.0 votes
^ source : crackstation.net/hashing-security.htm