Заменить замену FormsAuthentication.HashPasswordForStoringInConfigFile?
После обновления до .Net 4.5 я получаю предупреждение о том, что "System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile устарел", и рекомендуется использовать API-интерфейсы членства.
Это все очень хорошо и хорошо для новых проектов, но на данном этапе (с пользовательскими данными и хешированными паролями) я не могу нормально переключиться на пользовательский поставщик членства с потенциально разными способами хэширования.
Каков рекомендуемый путь для таких проблем? Продолжение использования "устаревших" вызовов, очевидно, не является предлагаемым путем, поэтому его заменили чем-то другим, кроме "просто использовать API-интерфейсы членства"?
Ответы
Ответ 1
Это решение для варианта SHA1.
public static string GetSwcSHA1(string value)
{
SHA1 algorithm = SHA1.Create();
byte[] data = algorithm.ComputeHash(Encoding.UTF8.GetBytes(value));
string sh1 = "";
for (int i = 0; i < data.Length; i++)
{
sh1 += data[i].ToString("x2").ToUpperInvariant();
}
return sh1;
}
Для MD5 вам нужно только изменить алгоритм на:
MD5 algorithm = MD5.Create();
Надеюсь, вы не против, просто добавив вариант VB.NET вашего кода выше:
Public Shared Function CreateHash(saltAndPassword) As String
Dim Algorithm As SHA1 = SHA1.Create()
Dim Data As Byte() = Algorithm.ComputeHash(Encoding.UTF8.GetBytes(saltAndPassword))
Dim Hashed As String = ""
For i As Integer = 0 To Data.Length - 1
Hashed &= Data(i).ToString("x2").ToUpperInvariant()
Next
Return Hashed
End Function
Ответ 2
Каков рекомендуемый путь для таких проблем? Продолжение использования "устаревших" вызовов, очевидно, не является предлагаемым путем, поэтому его заменили чем-то другим, кроме "просто использовать API-интерфейсы членства"?
Лучший способ (который вы исключили) исключительно в рамках .NET Framework - все это изменить, чтобы пароли хэшировали PBKDF2, Bcrypt или Scrypt. PBKDF2 предоставляется в .NET с помощью класса Rfc2898DeriveBytes.
Вторым лучшим способом является использование двух "версий" паролей:
- Версия 0 была бы старой версией HashPasswordForStoringInConfigFile, но вы можете обновлять ее в массовом порядке, в автономном режиме до версии 1 и удалять эти старые хэши целиком, прежде чем кто-нибудь их украдет, и вы попадете в торговые новости, имея жалкое 90-х старое хеширование паролей.
- Версия 1, которая является PBKDF2 существующего значения HashPasswordForStoringInConfigFile! То есть вы берете свои текущие неприятные старые хеши, и PBKDF2 их с новой случайной солью и большим количеством итераций, и сохраняйте результат. Затем, когда пользователь хочет войти в систему, вы передаете свой пароль на код @RichardBažant, поэтому у вас есть то, что HashPasswordForStoringInConfigFile вернет, а затем вы примените PBKDF2 к этому результату!
- то есть. это фактически Rfc2898DeriveBytes (HashPasswordForStoringInConfigFile (пароль)), PerUserSalt, YourIterations)
- Версия 2, для которой пользователи, у которых есть хеш-версия 1, обновлены. Все столбцы, кроме "версии", одинаковы, но после вычисления и проверки версии 1 вы вычисляете Rfc2898DeriveBytes (пароль), PerUserSalt, YourIterations) и заменяете хэш-версию версии 1 хешей версии 2 (и меняете версию на 2, конечно).
Третий лучший способ - второй лучший способ, но только с версией 1. Будьте осторожны, таким образом DCC2 безумие - вы продолжаете обертывание ваш старый вывод внутри новых алгоритмов
В обоих случаях вы будете хранить результаты PBKDF2-HMAC-SHA-1 в базе данных, поэтому вам понадобится:
- Пароль hash (BINARY (20)) - то есть выход PBKDF2.
- Ваша соль (BINARY (16), созданная для каждого пользователя RNGCryptoServiceProvider Class)
- Необязательно: количество итераций PBKDF2 (INT, начинающиеся с десятков тысяч и выше до того, как ваш сервер будет загружен с максимальной нагрузкой на CPU, увеличится по мере обновления вашего оборудования)
- Это позволяет вам прозрачно повышать уровень безопасности каждый раз, когда пользователь вводит свой (правильный) пароль. Сначала проверяя его правильность, а затем повторно запустив его с более высоким числом итераций.
- Необязательно: "версия" (TINYINT), так что позже перейти к другому алгоритму проще, так как вы можете иметь сразу несколько версий.
P.S. для нового алгоритма версии 1 или версии 2 Jither создал библиотеку .NET, способную к PBKDF2-HMAC-SHA256, PBKDF2-HMAC-SHA512 и т.д.; мой репозиторий Github содержит его вариант с разумным набором тестовых векторов.
Ответ 3
Ответ Ричарда работал у меня отлично.
Это код, скомпилированный из .NET Framework 4.5.
Если кто-то лучше, используйте его. Я думаю, это может быть немного быстрее.
public static string BinaryToHex(byte[] data)
{
if (data == null)
{
return null;
}
char[] hex = new char[checked((int)data.Length * 2)];
for (int i = 0; i < (int)data.Length; i++)
{
byte num = data[i];
hex[2 * i] = NibbleToHex((byte)(num >> 4));
hex[2 * i + 1] = NibbleToHex((byte)(num & 15));
}
return new string(hex);
}
private static char NibbleToHex(byte nibble)
{
int aChar = (nibble < 10 ? nibble + 48 : nibble - 10 + 65);
return (char)aChar;
}
Ответ 4
Почему нельзя использовать простейшую версию .Net
public static string HashString(string inputString, string hashName)
{
var algorithm = HashAlgorithm.Create(hashName);
if (algorithm == null)
throw new ArgumentException("Unrecognized hash name", hashName);
byte[] hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
return Convert.ToBase64String(hash);
}