Quel est l'algorithme de hachage par défaut utilisé par l'appartenance à ASP.NET? Et comment puis-je le changer?
À la lumière du fait que googler "algorithme de hachage du fournisseur d'adhésion" apparait cette réponse comme le premier résultat, et l'évangile qui sera inféré, il m'appartient d'avertir les gens d'utiliser le fournisseur d'adhésion comme celui-ci. et utiliser des hachages comme SHA-1, MD5, etc. pour masquer les mots de passe dans les bases de données.
tilisez une fonction de dérivation de clé comme bcrypt, scrypt ou (si vous avez besoin FIPS compliance) PBKDF2 avec un facteur de travail suffisant pour nécessitent un temps de hachage pour qu'un mot de passe unique soit aussi proche de 1000 ms ou plus.
Les hachages sont faciles à utiliser brutalement de nos jours avec de nombreux exemples de violations de données dans l'histoire récente. Pour empêcher les mots de passe de vos utilisateurs de se retrouver sur Pastebin dans le prochain hack, assurez-vous que les mots de passe sont hachés avec une fonction qui prend un suffisamment de temps pour calculer !
Au lieu de l'appartenance au fournisseur, essayez IdentityReboot ou les implémentations plus récentes de Microsoft dont Troy Hunt parle au moins.
Il est également intéressant de noter que sur les mêmes résultats Google mentionnés ci-dessus, je trouve un tutoriel montrant aux gens combien il est facile de forcer brutalement ces hachages de mot de passe à l'aide d'outils populaires comme JtR ou Hashcat. Sur une plate-forme GPU personnalisée, SHA1 peut être fissuré à un taux stupéfiant de 48867 millions de hachages par seconde! Avec un dictionnaire gratuit comme rockyou ou similaire , une personne motivée avec votre base de données aura très rapidement la plupart des mots de passe de vos utilisateurs. En tant que développeur, il est de votre responsabilité éthique de faire ce qui est nécessaire pour protéger la sécurité des mots de passe de vos utilisateurs.
Le hachage par défaut est SHA1 mais ils le salent également et le base64:
public string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
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);
}
Si vous voulez en savoir plus sur la façon de le changer, je dois encore le savoir (à moins d'utiliser un fournisseur personnalisé, voir ci-dessous), mais SHA-1 est assez bon pour l'instant. Si vous cherchez à l'inverser ou à chercher à partir de cela, ces gars-là ont travaillé sur cela: http://forums.asp.net/p/1336657/2899172.aspx
Cette SO aidera à inverser ou dupliquer cette technique si c'est ce qui pourrait être nécessaire. Réimplémenter l'appartenance à ASP.NET et le hachage de mot de passe utilisateur dans Ruby
Si vous créez un fournisseur personnalisé, vous pouvez créer vos algorithmes et méthodes de hachage et de chiffrement.
private byte[] ConvertPasswordForStorage(string Password)
{
System.Text.UnicodeEncoding ue =
new System.Text.UnicodeEncoding();
byte[] uePassword = ue.GetBytes(Password);
byte[] RetVal = null;
switch (_PasswordFormat)
{
case MembershipPasswordFormat.Clear:
RetVal = uePassword;
break;
case MembershipPasswordFormat.Hashed:
HMACSHA1 SHA1KeyedHasher = new HMACSHA1();
SHA1KeyedHasher.Key = _ValidationKey;
RetVal = SHA1KeyedHasher.ComputeHash(uePassword);
break;
case MembershipPasswordFormat.Encrypted:
TripleDESCryptoServiceProvider tripleDes = new
TripleDESCryptoServiceProvider();
tripleDes.Key = _DecryptionKey;
tripleDes.IV = new byte[8];
MemoryStream mStreamEnc = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(mStreamEnc,
tripleDes.CreateEncryptor(),
CryptoStreamMode.Write);
cryptoStream.Write(uePassword, 0, uePassword.Length);
cryptoStream.FlushFinalBlock();
RetVal = mStreamEnc.ToArray();
cryptoStream.Close();
break;
}
return RetVal;
}
private string GetHumanReadablePassword(byte[] StoredPassword)
{
System.Text.UnicodeEncoding ue = new System.Text.UnicodeEncoding();
string RetVal = null;
switch (_PasswordFormat)
{
case MembershipPasswordFormat.Clear:
RetVal = ue.GetString(StoredPassword);
break;
case MembershipPasswordFormat.Hashed:
throw new ApplicationException(
"Password cannot be recovered from a hashed format");
case MembershipPasswordFormat.Encrypted:
TripleDESCryptoServiceProvider tripleDes =
new TripleDESCryptoServiceProvider();
tripleDes.Key = _DecryptionKey;
tripleDes.IV = new byte[8];
CryptoStream cryptoStream =
new CryptoStream(new MemoryStream(StoredPassword),
tripleDes.CreateDecryptor(), CryptoStreamMode.Read);
MemoryStream msPasswordDec = new MemoryStream();
int BytesRead = 0;
byte[] Buffer = new byte[32];
while ((BytesRead = cryptoStream.Read(Buffer, 0, 32)) > 0)
{
msPasswordDec.Write(Buffer, 0, BytesRead);
}
cryptoStream.Close();
RetVal = ue.GetString(msPasswordDec.ToArray());
msPasswordDec.Close();
break;
}
return RetVal;
}
Le réponse ci-dessus de Ryan Christensen n'est pas complet. La partie où il convertit le sel en octet [] n'est pas correcte.
Voici un exemple de travail que j'ai implémenté dans une solution pour un client:
public string Hash(string value, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(value);
byte[] src = Convert.FromBase64String(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);
}
Le type d'algorithme de hachage par défaut est SHA1. Vous pouvez modifier cela de deux manières.
1) Si vous travaillez avec IIS 7, vous pouvez le mettre à jour en utilisant la configuration "Machine Key" (illustrée ci-dessous). Cela vous permet de choisir la méthode de cryptage dans une liste d'options disponibles et de spécifier les clés ou les options de génération de clés.
2) Si vous travaillez avec IIS 6, vous pouvez modifier le type d'algorithme de hachage en utilisant l'élément d'appartenance dans le fichier web.config:
<membership
defaultProvider="provider name"
userIsOnlineTimeWindow="number of minutes"
hashAlgorithmType="SHA1">
<providers>...</providers>
</membership>
Selon la documentation, la valeur de chaîne de l'attribut hashAlgorithmType peut être l'un des types d'algorithmes de hachage .Net fournis. Un peu de fouille montre que les valeurs valides pour ASP.Net 2, 3 et 3.5 sont MD5
, RIPEMD160
, SHA1
, SHA256
, SHA384
, SHA512
. La partie importante ici est que toutes ces classes héritent de HashAlgorithm
.
La valeur de l'attribut hashAlgorithmType peut également être une entrée de l'élément cryptoNameMapping du fichier machine.config. Vous pouvez l'utiliser si vous avez besoin d'un algorithme de hachage tiers. Le fichier machine.config se trouve généralement dans C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG
si vous utilisez ASP.Net 2 ou une version ultérieure. Vous pouvez en savoir plus sur la définition de ces valeurs ici .
L'algorithme de hachage par défaut est devenu HMACSHA256 dans le .NET 4.0 Framework.
Notez que contrairement à SHA-1, HMAC SHA-256 est un hachage à clé. Si vos hachages se comportent de manière non déterministe, vous n'avez probablement pas défini de clé, la forçant à en utiliser une au hasard. Quelque chose de semblable au suivant serait le coupable (c'est ce que je viens de passer une heure à comprendre: p).
HashAlgorithm.Create(Membership.HashAlgorithmType)
Si vous souhaitez le faire fonctionner avec un fournisseur existant, vous pouvez le restaurer aux anciens paramètres par défaut en utilisant ce guide .
Il y a une correction dans l'algorithme de hachage, vous devez utiliser:
byte[] src = Convert.FromBase64String(salt);
au lieu de
byte[] src = Encoding.Unicode.GetBytes(salt);
Lire l'article http://svakodnevnica.com.ba/index.php?option=com_kunena&func=view&catid=4&id=4&Itemid=5&lang=en#6
J'attache un extrait montrant le code comme dans la réponse de Rawbert ci-dessus en F #
open System
open System.Security.Cryptography
open System.Text
module PasswordHelper =
let EncodePassword(pass : string, salt : string) =
let bytes = Encoding.Unicode.GetBytes(pass)
let src = Convert.FromBase64String(salt)
let dst : byte array = Array.zeroCreate (src.Length + bytes.Length)
Buffer.BlockCopy(src, 0, dst, 0, src.Length)
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length)
let algorithm = HashAlgorithm.Create("SHA1")
let inArray = algorithm.ComputeHash(dst)
Convert.ToBase64String(inArray)
Il s'agit du code d'une application active