Эффективное шифрование пароля

В вашем конкретном случае вы можете установить содержащий элемент a следующим образом:

a {
    display: block;
    text-align: center;
}

JS Bin demo .

12
задан Community 23 May 2017 в 12:17
поделиться

8 ответов

Хм, я думаю, вам просто не хватает некоторых базовых концепций, связанных с работой хеширования. Позвольте мне попытаться кратко объяснить. Я собираюсь начать с простого и подробно изложить свой ответ позже, поэтому, пожалуйста, прочтите все, информация в начале не будет безопасной.

Вы хотите использовать для хранения пароля функцию, известную как «односторонний хеш». Это означает, что для любого ввода, который вы скармливаете функции, один и тот же ввод всегда будет давать один и тот же результат. Однако не существует математического процесса , который позволил бы вам взять эту строку результата и выяснить, каким был исходный ввод.

Давайте возьмем MD5 в качестве примера функции хеширования. Если я запустил MD5 со строкой «пароль», я всегда получу результат »

Теперь, даже если "перевернуть" хэш-функцию невозможно, тот факт, что один и тот же ввод всегда дает один и тот же вывод, означает, что кто-то может просто создать большую базу данных пар ввода / вывода и использовать ее для эффективного обращения хеши. Это называется «радужный стол». Многие из них доступны в Интернете, поэтому использовать простое хеширование небезопасно на случай, если ваша база данных когда-либо будет взломана. То есть, хотя математически невозможно взять «5f4dcc3b5aa765d61d8327deb882cf99» и вычислить, что оно пришло из запуска MD5 с «паролем», это очень легко определить на практике. Все, что вам нужно сделать, это пропустить каждое слово в словаре через MD5 и сохранить результаты, и вы можете легко изменить простые пароли.

Вот где » если он совпадает с сохраненным хешем, мы знаем, что они ввели правильный пароль.

Фактически то, что вы здесь сделали, так это то, что предварительно сгенерированные радужные таблицы бесполезны для попытки взломать пароли в вашей базе данных. Поскольку соль случайна и у каждого пользователя свой (обычно), злоумышленнику придется заново сгенерировать свои радужные таблицы для каждого отдельного пользователя . Это намного сложнее.

Однако есть еще одна проблема, и это то, что генерация хэшей MD5 выполняется быстро . Даже несмотря на то, что такое засоление требует от них повторного создания радужных таблиц, из-за того, насколько быстрым является MD5, некоторые прилично завершенные радужные таблицы могут быть созданы очень быстро. Поэтому, если они просто хотят взломать ценный аккаунт на вашем сайте, это Для них не так уж и важно потратить некоторое время на создание радужных таблиц, чтобы попытаться изменить этот пароль. Если исходный пароль важной учетной записи сам по себе не был достаточно безопасным, он все равно будет найден очень быстро, даже с использованием соления.

Итак, следующим шагом будет поиск медленной хэш-функции, и используйте его вместо быстрого, такого как MD5. Если вашему сайту потребуется дополнительная пара секунд для проверки логина, это совсем не проблема. Но когда кто-то пытается создать радужные таблицы для взлома пароля, то, что каждая запись занимает несколько секунд, является абсолютным убийцей. Я написал здесь достаточно, поэтому я просто закончу ссылкой на эту статью, в которой подробно рассказывается о выборе хорошей, медленной хеш-функции: Достаточно с радужными таблицами:

85
ответ дан 2 December 2019 в 02:49
поделиться

Хорошо, прежде всего пару вещей о классе Джеффа. SHA1 и MD5 устарели. CRC32 вообще не подходит для паролей. Во-вторых, вы должны солить каждый хэш, желательно с другим значением соли. Обычно для этого вы выбираете криптографически случайный блок данных, но при нажатии вы можете использовать имя пользователя. Чтобы посолить, вы префикс или суффикс значения соли где-нибудь в процессе. Я обычно хеширую пароль, хеширую соль, объединяю их, а затем снова хеширую. Но вы можете поменять местами, это не имеет большого значения, если вы последовательны.

Так что вместо того, чтобы путать вещи с классом Джеффа, давайте сделаем это классическим способом.

Во-первых, генерация случайной соли.

public static byte[] GetRandomSalt()
{
  int minSaltSize = 16;
  int maxSaltSize = 32;

  Random random = new Random();
  int saltSize = random.Next(minSaltSize, maxSaltSize);
  saltBytes = new byte[saltSize];
  RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
  rng.GetNonZeroBytes(saltBytes); 
  return saltBytes;
}

Затем хеширование

public static byte[] ComputeHash(string plainText)
{
  byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
  HashAlgorithm hash = new SHA256Managed();
  return hash.ComputeHash(plainTextWithSaltBytes);
}

Таким образом, будет вычислен хэш SHA256 и будет возвращен его как массив байтов.

Если бы вы солили, вы бы сделали что-то вроде следующего

byte[] passwordHash = ComputeHash(password);
byte[] salt = GetRandomSalt();
byte[] saltHash = ComputeHash(salt);

byte[] hashWithSaltBytes = new byte[hashBytes.Length + saltBytes.Length];
for (int i=0; i < hashBytes.Length; i++)
  hashWithSaltBytes[i] = hashBytes[i];
for (int i=0; i < saltBytes.Length; i++)
  hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i];

А затем, если вам скучно, хешируйте его снова или оставьте как есть.

Чтобы преобразовать байтовый массив в строку, если вы не думайте о хранении байтов, вы можете использовать

string hashValue = Convert.ToBase64String(hashWithSaltBytes);

Сравнение строк проще, чем сравнение байтов, когда вам нужно перебирать каждый массив на ваше усмотрение. Просто помните, что если вы используете случайные соли, их нужно хранить рядом с паролем.

7
ответ дан 2 December 2019 в 02:49
поделиться
  • Возьмите пароль пользователя « Секрет! ».
  • Создайте случайную соль из нескольких байтов « s4L75a1T ».
  • Concat их в « s4L75a1TSecret! ».
  • Вычислить хэш « b9797a5b683804eb195b6ba2a5e368ae74394cd3 » (это SHA-1 в шестнадцатеричном формате)
  • Сохраните хэш-код и его строка, строка Base64 или что угодно) в базе данных вместе с именем пользователя и другой информацией о пользователе (в примере соль представляет собой обычную строку, а хэш закодирован в Base64).
    FirstName    LastName    Salt        Hash
    -----------------------------------------------------------------
    John         Doe         s4L75a1T    uXl6W2g4BOsZW2uipeNornQ5TNM=

Если вы хотите проверить пароль пользователя, просто возьмите имя пользователя, найдите соль, повторите описанное выше и посмотрите, совпадают ли вычисленный хэш и хэш в базе данных. Не существует (известного) способа (легко) восстановить пароль.

6
ответ дан 2 December 2019 в 02:49
поделиться

Дон не путайте шифрование паролей с их хешированием; с хорошей криптографической хеш-функцией у вас не должно быть возможности отменить процесс хеширования для получения исходной строки.

Ответ Чада, приведенный выше, является отличным подробным объяснением задействованных концепций.

Эта тема была сделана. до смерти по всему Интернету; не только на Stack Overflow; серьезно - простой поиск в Интернете должен найти для вас довольно исчерпывающее руководство.

Спасибо, Джефф, за распространение еще одной кучи дезинформации. Полагаю, в течение следующей недели мы увидим множество ошибочных вопросов о хешировании, шифровании и т.д. не говоря уже об арифметике с плавающей точкой.

4
ответ дан 2 December 2019 в 02:49
поделиться

Я считаю, что процесс выглядит следующим образом: генерируют случайную соль, поэтому «рыбьи ножки» + «r4nd0mS4lt» получают «fishlegsr4nd0mS4lt». Затем вы хешируете это, скажем, с помощью MD5 (хотя вы можете использовать SHA256 для большей безопасности), чтобы получить: 593d5518d759b4860188158ef4c71f28. Сохраните это и случайно сгенерированную соль. Когда пользователь входит в систему, добавьте случайную соль и затем проверьте, совпадает ли введенный им пароль с солью с хешем в базе данных.

3
ответ дан 2 December 2019 в 02:49
поделиться

По сути, вы хотите сделать следующее:

A) При создании учетной записи вы получаете имя пользователя и пароль от пользователя, хешируете их вместе со своей собственной солью и сохраняете полученный результат. строка в своей базе данных, например:

Dim sUserName = "barry"
Dim sPassWord = "fishlegs"
Dim mySalt = "A deliciously salty string! fillED WIth all KindS of Junkk(&^&*(£"
Dim d As New Encryption.Data(mySalt + sUserName + sPassWord)
Dim hash As New Encryption.Hash(Encryption.Hash.Provider.SHA256)
hash.Calculate(d)
Dim sTheSaltedHashedUnPassCombination = hash.Value.Hex;
SavenewPasswordHashToDatabase(sTheSaltedHashedUnPassCombination)

Вы никогда не сохраняете sPassWord.

B) Когда пользователь входит в систему, вы выполняете точно такую ​​же операцию с предоставленным именем пользователя и паролем, а затем сравниваете полученный хэш с ранее сохраненным значением в базе данных, чтобы вы используете:

Dim sThePreviouslyCreatedHashFromTheDatabase = GetHashForUserFromDatabase(usernameProvided)
Dim mySalt = "A deliciously salty string! fillED WIth all KindS of Junkk(&^&*(£"
Dim d As New Encryption.Data(mySalt + usernameProvided+ passwordProvided)
Dim hash As New Encryption.Hash(Encryption.Hash.Provider.SHA256)
hash.Calculate(d)
Dim sTheSaltedHashedUnPassCombination = hash.Value.Hex;
if (sThePreviouslyCreatedHashFromTheDatabase.Equals(sTheSaltedHashedUnPassCombination))
    'UN & Password Valid!
else
    'UN & PW Invalid!
end

(Простите за любые ошибки, VB не мой язык)

Чтобы ответить на заданные вами вопросы:

1) См. выше. Никогда не храните пароль напрямую, сохраняйте хешированное значение

2) используйте символ (X), количество символов, возвращаемых хешем, является постоянным, поэтому вы можете указать ему известный размер хранилища.

3) То, что вы фактически сохраняете, - это пароль для пользователя с добавлением имени пользователя и константы на вашем сервере. Это будет строка фиксированной длины, и вы не сможете заменить эту строку на отдельные имя пользователя и пароль.

3
ответ дан 2 December 2019 в 02:49
поделиться
  1. Весь смысл хеширования в том, что вы храните хеши, а не пароли в виде открытого текста, и их невозможно восстановить (по крайней мере, с большим трудом). Хеш-функции спроектированы как односторонние, поэтому получение невозможно - в этом их суть.
  2. nchar [n] , вероятно, лучший вариант, поскольку обычные алгоритмы хеширования дают результаты постоянной длины ( SHA1 выводит 160-битный хеш). Обычной практикой является преобразование хэша в Base64 , чтобы его можно было сохранить как текст ASCII.
  3. Соль - это просто метод, который добавляет случайные биты к хешу, чтобы усложнить процесс взлома. Каждый дополнительный бит соли означает, что взломщик методом полного перебора должен занимать вдвое больше времени (и использовать вдвое больше памяти).
2
ответ дан 2 December 2019 в 02:49
поделиться

ASP.NET включает поставщика членства на основе SQL , который позволяет создавать, хранить и проверять зашифрованные или хешированные пароли без необходимости делать это что угодно - как говорит Эрик Липперт:

позвольте мне высказать вам все мои стандартные предостережения относительно развертывания ваших собственных криптографических алгоритмов и систем безопасности: не делайте этого.

0
ответ дан 2 December 2019 в 02:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: