Ответ 1
РЕДАКТИРОВАТЬ: не использовать членство-член как есть, потому что он ужасно неадекватен с точки зрения защиты паролей пользователей
В свете того, что googling "алгоритм хеширования поставщика членства" , этот ответ становится первым, а Евангелие, которое будет быть выведенным, мне надлежит предупреждать людей об использовании поставщика членства, подобного этому, и использовать хэши, такие как SHA-1, MD5 и т.д., чтобы запутать пароли в базах данных.
TL;DR
Используйте функцию генерации ключа, такую как bcrypt, scrypt или (если вам нужно соответствие FIPS) PBKDF2 с достаточным рабочим коэффициентом чтобы время хэширования для одного пароля было как можно ближе к 1000 мс или более.
Хэши в наши дни легко переборщить с обильными примерами нарушений данных в новейшей истории. Чтобы ваши пароли пользователей не попали в pastabin в следующем хаке, убедитесь, что пароли хэшируются с помощью функции, которая занимает достаточно много времени для вычисления!
Вместо поставщика членства попробуйте IdentityReboot или более новые версии от Microsoft, о которых Troy Hunt говорит о как минимум.
Также интересно, что по тем же результатам google, о которых говорилось выше, я нахожу учебник в котором люди очень ценят, насколько легко это сделать, чтобы переборщить эти пароли хэши, используя популярные инструменты, такие как JtR или Hashcat. На пользовательской платформе GPU SHA1 может быть взломан на ошеломляющая скорость 48867 миллионов хэшей в секунду! С бесплатным словарем, например rockyou или тому подобное, у мотивированного человека с вашей базой данных очень быстро будет большая часть ваших паролей пользователей. Как разработчик, ваша этическая ответственность - делать то, что необходимо для защиты паролей ваших пользователей.
Хеширование по умолчанию - SHA1, но они также сольют его и 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);
}
Если вы хотите узнать больше о том, как его изменить, мне все равно нужно выяснить (если не использовать пользовательский провайдер, см. ниже), однако SHA-1 сейчас довольно хорош. Если вы хотите отменить это или посмотрите на это, эти ребята немного поработали над этим: http://forums.asp.net/p/1336657/2899172.aspx
Этот SO-вопрос поможет в обратном или дублировании этого метода, если это то, что может понадобиться. Переопределить членство в ASP.NET и пользовательский пароль в Ruby
Если вы создаете настраиваемый поставщик, вы можете создать свои алгоритмы и методы хеширования и шифрования.
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;
}