Как измерить силу пароля?

Я искал эффективный алгоритм, который может дать мне точное представление о том, насколько сильный пароль.

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

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


Убедитесь, что вы используете SSL для всех операций с информацией пользователя. Все страницы, которые связаны с этими формами, должны проверять, что они вызываются через HTTPS, и отказываются работать иначе.

Вы можете устранить большинство атак, просто ограничив количество разрешенных логинов.

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

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

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

К сожалению, ограничение количества логинов, разрешенных для каждого IP-адреса, нецелесообразно. Некоторые поставщики, такие как AOL и большинство компаний, проксируют свои веб-запросы. Наложение этого ограничения эффективно устранит этих пользователей.


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

Проверка на наличие слабых паролей минус слова словаря Практическая клиентская сторона с некоторым простым javascript.

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

Как только вы довольны паролем, который они выбрали, сначала зашифруйте его с помощью PHP, а затем сохраните. Следующая функция шифрования пароля также не является моей идеей, но решает ряд проблем. Шифрование внутри PHP предотвращает перехват ваших незашифрованных паролей на общем сервере. Добавление чего-то пользователя, который не изменится (я использую адрес электронной почты, так как это имя пользователя для моих сайтов) и добавить хеш (SALT – это короткая константная строка, которую я меняю на сайт) повышает устойчивость к атакам. Поскольку SALT находится внутри пароля, а пароль может быть любой длины, становится практически невозможно атаковать это с помощью стола радуги. В качестве альтернативы это также означает, что люди не могут изменить свою электронную почту, и вы не можете изменить СОЛЬ, но не аннулируете пароль каждого.

EDIT: Я бы рекомендовал вместо этого использовать PhPass вместо моей собственной функции или просто забыть логины пользователей и использовать OpenID .

function password_crypt($email,$toHash) { $password = str_split($toHash,(strlen($toHash)/2)+1); return hash('sha256', $email.$password[0].SALT.$password[1]); } 

Мой счетчик пароля клиента Jqueryish. Цель должна быть div. Его ширина изменится от 0 до 100, а цвет фона изменится на основе классов, обозначенных в скрипте. Снова в основном украдены из других вещей, которые я нашел:

 $.updatePasswordMeter = function(password,username,target) { $.updatePasswordMeter._checkRepetition = function(pLen,str) { res = "" for ( i=0; i<str.length ; i++ ) { repeated=true; for (j=0;j < pLen && (j+i+pLen) < str.length;j++) repeated=repeated && (str.charAt(j+i)==str.charAt(j+i+pLen)); if (j<pLen) repeated=false; if (repeated) { i+=pLen-1; repeated=false; } else { res+=str.charAt(i); }; }; return res; }; var score = 0; var r_class = 'weak-password'; //password < 4 if (password.length < 4 || password.toLowerCase()==username.toLowerCase()) { target.width(score + '%').removeClass("weak-password okay-password good-password strong-password" ).addClass(r_class); return true; } //password length score += password.length * 4; score += ( $.updatePasswordMeter._checkRepetition(1,password).length - password.length ) * 1; score += ( $.updatePasswordMeter._checkRepetition(2,password).length - password.length ) * 1; score += ( $.updatePasswordMeter._checkRepetition(3,password).length - password.length ) * 1; score += ( $.updatePasswordMeter._checkRepetition(4,password).length - password.length ) * 1; //password has 3 numbers if (password.match(/(.*[0-9].*[0-9].*[0-9])/)) score += 5; //password has 2 symbols if (password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)) score += 5; //password has Upper and Lower chars if (password.match(/([az].*[AZ])|([AZ].*[az])/)) score += 10; //password has number and chars if (password.match(/([a-zA-Z])/) && password.match(/([0-9])/)) score += 15; // //password has number and symbol if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/)) score += 15; //password has char and symbol if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/)) score += 15; //password is just a nubers or chars if (password.match(/^\w+$/) || password.match(/^\d+$/) ) score -= 10; //verifing 0 < score < 100 score = score * 2; if ( score < 0 ) score = 0; if ( score > 100 ) score = 100; if (score > 25 ) r_class = 'okay-password'; if (score > 50 ) r_class = 'good-password'; if (score > 75 ) r_class = 'strong-password'; target.width(score + '%').removeClass("weak-password okay-password good-password strong-password" ).addClass(r_class); return true; }; 

В основном вы хотите предотвратить основные типы атак

  • Атаки словаря
  • Атаки грубой силы

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

Быстрый поиск google нашел решения, которые учитывают атаки грубой силы (сложный пароль), но не для атак на словаря. PHP-метр прочности пароля из этого списка проверок прочности запускает проверку на стороне сервера, поэтому его можно расширить, чтобы проверить словарь.

РЕДАКТИРОВАТЬ:

Кстати … вы также должны ограничить количество попыток входа на пользователя. Это уменьшит вероятность возникновения обоих типов атак. Эффективный, но не удобный для пользователя способ блокировки учетной записи после X неудачных попыток и требует сброса пароля. Более дружелюбный пользователь, но больше усилий – это время дросселирования между попытками входа в систему. Вы также можете потребовать CAPTCHA после первых попыток входа (это то, что требуется переполнение стека после слишком большого количества изменений или для очень новых пользователей).

В основном вы, вероятно, хотите использовать регулярные выражения для проверки длины и сложности пароля.

Хороший пример этого с помощью javascript можно найти здесь:

http://marketingtechblog.com/programming/javascript-password-strength/

Как указал Дарен Швенке, вам лучше поработать над безопасностью и не поместить это в руки пользователя .

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

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

В основном, вы должны проверить смысл commom: проверьте, содержит ли пароль буквы, цифры и не алфавитные символы в разумном количестве.

Вы можете легко взломать свой собственный алгоритм: просто сделайте отметку 10/10:

  • 0 – пароль с нулевой длиной;
  • +2 для каждых 8 символов в пароле (15 предполагается, что это безопасная длина);
  • +1 для использования буквы, +2 для использования 2 букв;
  • +1 для использования числа, +2 для использования 2 чисел;
  • +1 для использования не алфавитных символов, +2 для 2.

Вам не нужно проверять божественные пароли (есть ли буквы с заглавными буквами, где расположены специальные символы и т. Д.), Ваши пользователи не находятся в банковской / военной / секретной службе / в индустрии фильмов python в месяц, не так ли?

Вы можете закодировать это через час без безумных навыков javascript.

И вообще, действуйте на пароле и переместите весь код безопасности на стороне сервера. Если вы можете делегировать аутентификацию (например: открытый идентификатор), еще лучше.

Я не могу придумать конкретный алгоритм проверки силы пароля. Мы делаем то, что мы определяем несколько критериев, и когда пароль соблюдает критерии, мы добавляем 1 к его счету. Когда пароль достиг порога, пароль сильный. В противном случае он слаб.

Вы можете определить много разных уровней strengh, если с разными способами, или вы можете определить другое значение для определенных критериев. Например, если пароль имеет 5 символов, мы добавляем 1, но если он получил 10, добавим 2.

вот список критериев для проверки

Длина (от 8 до 12 в порядке, больше лучше) Содержит строчную букву Содержит прописную букву Верхняя буква НЕ является первой. Содержит номер Содержит символы, последний символ НЕ является символом человека (например: или!). Не похож на словарное слово. Некоторая мудрая трещина пароля содержит библиотеку заменителей слов и букв (например, Library -> L1br @ ry)

Надеюсь, что это поможет.

Не сворачивайте свой собственный!

Криптографические эксперты не рекомендуют криптографию криптографии по причинам, которые должны быть очевидны.

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

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

Это сложная проблема

Есть значительные трудности, связанные с проблемой измерения силы пароля. Чем больше исследований я занимаюсь на эту тему, тем больше я понимаю, что это «однонаправленная» проблема; то есть невозможно измерить «трудность» (вычислительную стоимость) эффективного взлома пароля. Скорее, более эффективно предоставлять требования к сложности и измерять способность пароля выполнять их.

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

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

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

Жизнеспособное решение

В Openwall имеется автономная утилита, называемая passwdqc (предположительно, для проверки качества пароля ). Разработчик Openwall, Solar Designer, по-видимому, является добросовестным специалистом по криптографии (его работы говорят сами за себя), и поэтому квалифицирован для создания такого инструмента.

Для моего конкретного случая использования это гораздо более привлекательное решение, чем использование плохо продуманного фрагмента JavaScript, живущего в каком-то темном углу Интернета.

Наиболее сложной является настройка параметров для ваших конкретных потребностей. Реализация – легкая часть.

Практический пример

Я предлагаю простую реализацию в PHP, чтобы обеспечить начало перехода. Применяются стандартные отказы.

В этом примере предполагается, что мы загружаем весь список паролей в PHP-скрипт. Само собой разумеется, что если вы делаете это с настоящими паролями (например, сбрасываемыми из менеджера паролей), следует проявлять особую осторожность в отношении обработки паролей. Простое создание незашифрованного паролей дампов на диск ставит под угрозу безопасность ваших паролей!

passwords.csv :

 "Title","Password" "My Test Password","password123" "Your Test Password","123456!!!" "A strong password","NFYbCoHC5S7dngitqCD53tvQkAu3dais" 

password-check.php :

 <?php //A few handy examples from other users: //http://php.net/manual/en/function.str-getcsv.php#117692 $csv = array_map('str_getcsv', file('passwords.csv'), [',']); array_walk($csv, function(&$a) use ($csv) { $a = array_combine($csv[0], $a); }); //Remove column header. array_shift($csv); //Define report column headers. $results[] = [ 'Title', 'Result', 'Exit Code', ]; $i = 1; foreach ($csv as $p) { $row['title'] = $p['Title']; //If the value contains a space, it's considered a passphrase. $isPassphrase = stristr($p['Password'], ' ') !== false ? true : false; $cmd = 'echo ' . escapeshellarg($p['Password']) . ' | pwqcheck -1 min=32,24,22,20,16 max=128'; if ($isPassphrase) { $cmd .= ' passphrase=3'; } else { $cmd .= ' passphrase=0'; } $output = null; $exitCode = null; $stdOut = exec($cmd, $output, $exitCode); //Exit code 0 represents an unacceptable password (not an error). //Exit code 1 represents an acceptable password (it meets the criteria). if ($exitCode === 0 || $exitCode === 1) { $row['result'] = trim($stdOut); $row['exitCode'] = $exitCode; } else { $row['result'] = 'An error occurred while calling pwqcheck'; $row['exitCode'] = null; } $results[$i] = $row; $i++; } $reportFile = 'report.csv'; $fp = @fopen($reportFile, 'w'); if ($fp !== false) { foreach ($results as $p) { fputcsv($fp, $p); } fclose($fp); } else { die($reportFile . ' could not be opened for writing (destination is not writable or file is in use)'); } exit; 

Результирующий report.csv :

 Title,Result,"Exit Code" "My Test Password","Bad passphrase (too short)",1 "Your Test Password","Bad passphrase (too short)",1 "A strong password",OK,0 

Обертывание-Up

Мне еще предстоит найти более тщательное решение в Интернете; Разумеется, я приветствую любые другие рекомендации.

Очевидно, что этот подход не идеален для определенных случаев использования (например, «счетчик прочности пароля» реализован «на стороне клиента»). Тем не менее, было бы тривиально сделать вызов AJAX на серверный ресурс, который возвращает ответ pass / fail, используя описанный выше подход, но такой подход должен предполагать возможность злоупотребления (например, DoS-атаки) и потребовать безопасная связь между клиентом и сервером, а также принятие рисков, связанных с передачей не-хэшированного пароля.