Пишем свой генератор паролей
Готовый код с уникальным алгоритмом шифрования. Возьми и сделай.
Недавно мы писали про уязвимость паролей в фейсбуке и про способы их шифрования. Настало сделать свой собственный генератор паролей с хешем и секретной строкой. Пройдите с нами этот путь, и у вас появится собственное приложение для создание паролей, которое вы сможете сделать сколько угодно секретным, а при желании — воссоздать.
В этом уроке мы создадим страницу, которая будет генерировать пароли для любых сайтов. На входе вы будете давать ей адрес сайта, а на выходе она даст вам безопасный уникальный пароль. Безопасность будет достигаться за счет секретного слова и особого алгоритма шифрования. Также вы сможете вспомнить пароль от любого сайта, если знаете секретное слово и адрес сайта.
Как устроен наш алгоритм
Мы будем брать адрес сайта и шифровать его с помощью алгоритма хеширования MD5. Результат шифрования и будет нашим паролем.
О хешировании мы уже писали, общий смысл такой: особый алгоритм шифрует текст таким образом, что по итоговому зашифрованному тексту невозможно восстановить исходный. Непонятна ни длина исходного текста, ни его содержимое.
Слабое место алгоритма только в том, что если зашифровать им один и тот же текст, получится один и тот же результат. То есть алгоритм работает предсказуемо: если зашифровать адрес mail.yandex.ru с помощью алгоритма MD5, всегда получится B81D1C770FD8F323B57CC73ED7B2546E. Это небезопасно.
Чтобы пароли были более уникальными, мы добавим к адресу сайта секретное слово, которое попросим у пользователя. И еще одно секретное слово впишем прямо в код программы. Вот эти два секретных слова и будут обеспечивать нашу безопасность пароля.
Всё, что осталось сделать — склеить адрес сайта и два секретных слова, зашифровать алгоритмом MD5, и вуаля — у нас будет уникальный трудночитаемый пароль, который никто никогда не подберет перебором.
Готовим каркас
За основу мы возьмём страницу, которую мы создавали, когда делали свой список задач. Если вы её ещё не читали — почитайте, будет гораздо легче понимать, что тут происходит. В нашем случае каркас будет выглядеть так:
Сохраняем файл как generator.html, открываем в браузере и видим пока пустую страницу с заголовком вкладки «Генератор паролей» и больше ничего. Всё нормально, так и должно быть.
Расставляем содержимое
Вот какой минимум информации должен быть на нашей странице с генератором:
Разместим всё это на странице в разделе в том же порядке:
Сохраняем под тем же именем смотрим что получилось и не расстраиваемся от внешнего вида. Его мы поправим на следующем шаге.
Настраиваем стили
Стили помогают улучшить внешний вид страницы и установить нужный размер шрифта, его расположение, отступы, да и вообще всё, что мы видим на экране. Добавим стилей в наш генератор в раздел
Генератор случайных паролей на JavaScript
Разработчик под ником Foolish Developer опубликовал пошаговое руководство по созданию генератора надежных и уникальных паролей с помощью JavaScript, HTML и CSS. Пароли генерируются на основе специальных символов, букв и цифр.
Структура генератора
Ниже представлен итоговый вид генератора. Он состоит из фона, маленькой рамки с текстом, поля, а также кнопок для создания и копирования пароля.
Шаг 1: создание поля с помощью HTML- и CSS-кода
Код ниже создает на веб-странице поле. Автор задал фиолетовый цвет фона веб-страницы, а цветом фона рамки указал белый.
Шаг 2: добавление заголовка в рамке
Заголовок создается следующим кодом:
Шаг 3: создание поля для генерации кода
Шаг 4: создание кнопок для генерации и копирования пароля
Шаг 5: активация кнопки генерации кода с помощью JavaScript
Для начала нужно установить переменную ID входа ( password ).
С помощью var passwordLength указывается количество символов в будущем пароле.
Далее пароль связывается с полем ввода.
Шаг 6: Активация кнопки копирования пароля
С помощью кода ниже все, что написано в поле ввода, можно будет скопировать запрограммированной кнопкой.
Шаг 7: Окончательный JavaScript-код
Генератор паролей для сайта
Дата публикации: 2013-11-14
От автора: при создании механизма регистрации пользователей на сайте, иногда возникает необходимость генерации пароля для пользователя. Так как пароли, придуманные пользователями для своих учетных записей, зачастую очень просты, а значит, уязвимы для злоумышленников. Поэтому в данном уроке мы с Вами создадим генератор паролей для сайта, благодаря которому Вы сможете обеспечить высокую безопасность создаваемых учетных записей.
Постановка задачи
Для сегодняшнего урока, я создал очень простую html страницу, которую мы будем использовать для сегодняшнего скрипта:
Бесплатный курс по PHP программированию
Освойте курс и узнайте, как создать динамичный сайт на PHP и MySQL с полного нуля, используя модель MVC
В курсе 39 уроков | 15 часов видео | исходники для каждого урока
Вот исходный код, данной страницы:
Используя данную страницу, мы с Вами должны создать скрипт, который будет выполнять генерацию пароля для пользователя. Конечно, решить данную задачу можно различными способами, но перед этим, давайте определимся какой, пароль должен получиться в результате генерации, что бы он был безопасным.
Итак, какой же пароль является безопасным? Это такой пароль, который очень сложно подобрать, так как очень часто процесс взлома учетной записи сводится к простому подбору пароля – то есть перебор символов, пока не найдется подходящая последовательность. Поэтому, согласитесь, если пароль будет состоять из малого количества символов и, к примеру, только из малых английских букв – его будет очень легко подобрать. Но если же мы создадим пароль, состоящий из малых и больших букв, а также включающий в себя цифры – это уже будет довольно сложный и безопасный пароль. Поэтому мы с Вами в данном уроке, реализуем генерацию двух видов паролей. Итак, давайте приступим.
PassGenJS. Генерируем пароли в Javascript с указанием надёжности
В одном проекте появилась необходимость генерации надежного пароля на клиенте. Поискал готовое решение, но ничего подходящего не нашел.
Все библиотеки, которые нашлись, не подходили по ряду причин — генерировали пароль просто по желаемой длине, отсутствовала возможность проверки надёжности пароля. Решено было писать свой «велосипед» — как альтернативное решение, да и опыт лишним не будет. В итоге получилась библиотечка PassGenJS.
Приведу несколько примеров:
Генерируем надёжный пароль:
Генерируем очень простой пароль:
Генерируем пароль c 60% надежностью:
Генерируем пароль c символьными параметрами:
Также есть возможность проверить надёжность пароля:
Алгоритм оценки, используемый в данном плагине, опирается на общие положения теории информации.
В качестве оценки стойкости пароля используется значение его энтропии. Подробнее можно почитать на Wikipedia.
Под энтропией (информационной ёмкостью) пароля подразумевается мера случайности выбора последовательности символов, составляющих пароль, оцененная методами теории информации. В качестве формулы, использующейся для определения энтропии пароля используется
где N — это количество возможных символов, а L — количество символов в пароле. H измеряется в битах.
Генерируем одноразовые пароли для 2FA в JS с помощью Web Crypto API
Введение
Двухфакторная аутентификация сегодня повсюду. Благодаря ей, чтобы украсть аккаунт, недостаточно одного лишь пароля. И хотя ее наличие не гарантирует, что ваш аккаунт не уведут, чтобы ее обойти, потребуется более сложная и многоуровневая атака. Как известно, чем сложнее что-либо в этом мире, тем больше вероятность, что работать оно не будет.
Уверен, все, кто читают эту статью, хотя бы раз использовали двухфакторную аутентификацию (далее — 2FA, уж больное длинное словосочетание) в своей жизни. Сегодня я приглашаю вас разобраться, как устроена эта технология, ежедневно защищающая бесчисленное количество аккаунтов.
Но для начала, можете взглянуть на демо того, чем мы сегодня займемся.
Основы
Первое, что стоит упомянуть про одноразовые пароли, — это то, что они бывают двух типов: HOTP и TOTP. А именно, HMAC-based One Time Password и Time-based OTP. TOTP — это лишь надстройка над HOTP, поэтому сначала поговорим о более простом алгоритме.
HOTP описан спецификацией RFC4226. Она небольшая, всего 35 страниц, и содержит все необходимое: формальное описание, пример реализации и тестовые данные. Давайте рассмотрим основные понятия.
Прежде всего, что такое HMAC? HMAC расшифровывается как Hash-based Message Authentication Code, или по-русски «код аутентификации сообщений, использующий хэш-функции». MAC — это механизм, позволяющий верифицировать отправителя сообщения. Алгоритм MAC генерирует MAC-тэг, используя секретный ключ, известный только отправителю и получателю. Получив сообщение, вы можете сгенерировать MAC-тэг самостоятельно и сравнить два тэга. Если они совпадают — все в порядке, вмешательства в процесс коммуникации не было. В качестве бонуса этим же способом можно проверить, не повредилось ли сообщение при передаче. Конечно, отличить вмешательство от повреждения не выйдет, но достаточно самого факта повреждения информации.
Что же такое хэш? Хэш — это результат применения к сообщению Хэш-функции. Хэш-функции берут ваши данные и делают из него строку фиксированной длины. Хороший пример — всем известная функция MD5, которая широко использовалась для проверки целостности файлов.
Сам по себе MAC — это не конкретный алгоритм, а лишь общий термин. HMAC в свою очередь — уже конкретная реализация. Если точнее, то HMAC-X, где X — одна из криптографических хэш-функций. HMAC принимает два аргумента: секретный ключ и сообщение, смешивает их определенным образом, применяет выбранную хэш-функцию два раза и возвращает MAC-тэг.
Если вы сейчас думаете про себя, какое отношение все это имеет к одноразовым паролям — не волнуйтесь, мы почти дошли до самого главного.
Согласно спецификации, HOTP вычисляется на основе двух значений:
Счетчик — это 8-байтовое значение, синхронизированное между клиентом и сервером. Оно обновляется, по мере того как вы генерируете новые пароли. В схеме HOTP счетчик на стороне клиента инкрементируется каждый раз, когда вы генерируете новый пароль. На стороне сервера — каждый раз, когда пароль успешно проходит валидацию. Так как можно сгенерировать пароль, но не воспользоваться им, сервер позволяет значению счетчика немного забегать вперед в пределах установленного окна. Однако если вы слишком заигрались с генератором паролей в схеме HOTP, придется синхронизировать его повторно.
Итак. Как вы, наверное, заметили, HMAC тоже принимает два аргумента. RFC4226 определяет функцию генерации HOTP следующим образом:
Вполне ожидаемо, K используется в качестве секретного ключа. Счетчик, в свою очередь, используется в качестве сообщения. После того, как HMAC функция сгенерирует MAC-тэг, загадочная функция Truncate вытаскивает из результата уже знакомый нам одноразовый пароль, который вы видите в своем приложении-генераторе или на токене.
Давайте начнем писать код и разберемся с остальным по ходу дела.
План реализации
Чтобы заполучить одноразовые пароли, нам понадобится выполнить следующие шаги.
Звучит не слишком сложно, правда? Начнем с генерации хэша.
Генерируем HMAC-SHA1
Это, пожалуй, самый простой из перечисленных выше шагов. Мы не будем пытаться воссоздать алгоритм самостоятельно (никогда не надо самостоятельно пытаться реализовать что-то из криптографии). Вместо этого мы воспользуемся Web Crypto API. Небольшая проблема заключается в том, что это API по спецификации доступно только под Secure Context (HTTPS). Для нас это чревато тем, что мы не сможем пользоваться им, не настроив HTTPS на сервере разработки. Немного истории и дискуссии на тему того, насколько это правильное решение, вы можете найти здесь.
К счастью, в Firefox вы можете использовать Web Crypto в незащищенном контексте, и изобретать колесо или приплетать сторонние библиотеки не придется. Поэтому для целей разработки демо предлагаю воспользоваться FF.
Теперь соберем все вместе:
Отлично! Криптографию заготовили. Теперь разберемся со счетчиком и, наконец, подпишем сообщение.
И на этом мы завершили первый шаг. На выходе мы получаем немного загадочно называющееся значение HS. И хотя это не самое лучшее название для переменной, именно так она (и некоторые последующие) называются в спецификации. Оставим эти названия, чтобы проще было сравнивать с ней код. Что дальше?
Step 2: Generate a 4-byte string (Dynamic Truncation)
Let Sbits = DT(HS) // DT, defined below,
// returns a 31-bit string
DT расшифровывается как Dynamic Truncation. И вот как она работает:
Почти закончили! Осталось лишь сконвертировать полученное от DT значение в число и вперед, к третьему шагу.
Код для заключительной функции, которая объединяет все предыдущие, в таком случае будет выглядеть как-то так:
Ура! Но как теперь проверить, что наш код верный?
Тестирование
Для того чтобы протестировать реализацию, воспользуемся примерами из RFC. Приложение D включает в себя тестовые значения для секретного ключа «12345678901234567890» и значений счетчика от 0 до 9. Также там есть подсчитанные хэши HMAC и промежуточные результаты функции Truncate. Довольно полезно для отладки всех шагов алгоритма. Вот небольшой пример этой таблицы (оставлены только счетчик и HOTP):
Если вы еще не смотрели демо, сейчас самое время. Можете повбивать в нем значения из RFC. И возвращайтесь, потому что мы приступаем к TOTP.
Вот мы, наконец, и добрались до более современной части 2FA. Когда вы открываете свой генератор одноразовых паролей и видите маленький таймер, отсчитывающий, сколько еще будет валиден код, — это TOTP. В чем разница?
Time-based означает, что вместо статического значения, в качестве счетчика используется текущее время. Или, если точнее, «интервал» (time step). Или даже номер текущего интервала. Чтобы вычислить его, мы берем Unix-время (количество миллисекунд с полуночи 1 января 1970 года по UTC) и делим на окно валидности пароля (обычно 30 секунд). Сервер обычно допускает небольшие отклонения ввиду несовершенства синхронизации часов. Обычно на 1 интервал вперед и назад в зависимости от конфигурации.
Очевидно, это гораздо безопаснее, чем схема HOTP. В схеме, завязанной на время, валидный код меняется каждые 30 секунд, даже если он не был использован. В оригинальном алгоритме валидный пароль определен текущим значением счетчика на сервере + окном допуска. Если вы не аутентифицируетесь, пароль не будет изменен бесконечно долго. Больше про TOTP можно почитать в RFC6238.
Поскольку схема с использованием времени — это дополнение к оригинальному алгоритму, нам не потребуется вносить изменения к изначальной реализации. Мы воспользуемся requestAnimationFrame и будем на каждый фрейм проверять, до сих пор ли мы находимся внутри временного интервала. Если нет — генерируем новый счетчик и вычисляем HOTP заново. Опуская весь управляющий код, решение выглядит как-то так:
Последние штрихи — поддержка QR-кодов
Обычно, когда мы настраиваем 2FA, мы сканируем начальные параметры с QR-кода. Он содержит всю необходимую информацию: выбранную схему, секретный ключ, имя аккаунта, имя провайдера, количество цифр в пароле.
Закодированная в QR-код ссылка имеет следующий формат:
Я опущу код, который настраивает процесс запуска захвата экрана и распознавания, так как все это можно найти в документации. Вместо этого, вот как можно распарсить эту ссылку:
В реальном мире секретный ключ будет закодированной в base-32 (!) строкой, поскольку некоторые байты могут быть непечатными. Но для простоты демонстрации мы опустим этот момент. К сожалению, я не смог найти информации, почему именно base-32 или именно такой формат. По всей видимости, никакой официальной спецификации к этому формату URL не существует, а сам формат был придуман Google. Немного о нем вы можете почитать здесь
Для генерации тестовых QR-кодов рекомендую воспользоваться FreeOTP.
Заключение
И на этом все! Еще раз, не забывайте посмотреть демо. Там же есть ссылка на репозиторий с кодом, который за этим всем стоит.
Сегодня мы разобрали достаточно важную технологию, которой пользуемся на ежедневной основе. Надеюсь, вы узнали для себя что-то новое. Эта статья заняла гораздо больше времени, чем я думал. Однако довольно интересно превратить бумажную спецификацию в нечто работающее и такое знакомое.