#c#
#c#
Вопрос:
Я столкнулся с любопытным поведением при попытке хэшировать строковый пароль, а затем отобразить хэш в консоли.
Мой код:
static void Main(string[] args)
{
string password = "password";
ConvertPasswordToHash(password);
}
private static void ConvertPasswordToHash(string password)
{
using (HashAlgorithm sha = SHA256.Create())
{
byte[] result = sha.ComputeHash(Encoding.UTF8.GetBytes(password));
string hashText = Encoding.UTF8.GetString(result);
Console.WriteLine(hashText);
StringBuilder sb = new StringBuilder();
foreach (var item in result)
{
sb.Append((char)item);
}
Console.WriteLine(sb);
}
}
Проблема двоякая:
- hashTest и sb содержат разные значения (оба задолго до вывода составляют 32 символа), и 2) Выходные данные консоли еще более странные. Они не имеют длины 32 символа, а во-вторых, выходные данные немного отличаются:
При проверке строк перед их выводом я заметил, что hashText содержит, например, u0004, который может быть каким-либо символом юникода, в то время как sb вообще не содержит его (то есть до вывода значений в консоль).
Мои вопросы:
- Какой способ является правильным способом получения строки символов из предоставленного массива байтов?
- Почему выходные данные консоли отличаются, но лишь незначительно? Не похоже, что это ошибка использования неправильной кодировки.
- Как мне вывести правильный хэш (32 символа) в консоль? Я попытался добавить ‘@’ перед строками, чтобы отменить любые возможные возвраты каретки и т.д… Практически без какого-либо результата.
Возможно, я упускаю что-то очевидное. Спасибо.
Комментарии:
1. Вы могли бы попробовать кодирование результата в base64. Имейте в виду, что хэш — это число, а не текст
2. Немного не по теме, но использование SHA256 для паролей — плохая практика. Вместо этого используйте правильную функцию хэширования паролей.
3. Почему вы пытаетесь кому-либо показывать хэши паролей? То, что хэш более безопасен, чем обычный текстовый пароль, не означает, что вы должны быть более либеральными в показе его другим.
4. @Servy конечно, я не хочу делать это на производстве. Я не чувствовал необходимости указывать. Я просто играл с хэшами и наткнулся на это.
5. Подойдет любой алгоритм, специально разработанный для хранения паролей. В .NET есть встроенная реализация PBKDF2, bcrypt — еще одна распространенная, или более новые альтернативы, такие как Argon2, например. Любой хэш общего назначения, такой как MD5, SHA1, любой SHA2 или SHA3, плох для паролей, потому что они быстрые . Посмотрите здесь для получения дополнительной информации: security.stackexchange.com/questions/211 /…
Ответ №1:
Правильная логика должна быть следующей:
private static void ConvertPasswordToHash(string password)
{
using (HashAlgorithm sha = SHA256.Create())
{
byte[] result = sha.ComputeHash(Encoding.UTF8.GetBytes(password));
StringBuilder sb = new StringBuilder();
foreach (var item in result)
{
sb.Append(item.ToString("x2"));
}
Console.WriteLine(sb);
}
}
ToString("x2")
форматирует строку в виде двух шестнадцатеричных символов.
Живой пример:https://dotnetfiddle.net/QkREkX
Другой способ — просто представить ваш byte[]
массив в виде базовой строки 64, не StringBuilder
требуется.
byte[] result = sha.ComputeHash(Encoding.UTF8.GetBytes(password));
Console.WriteLine(Convert.ToBase64String(result));