Насколько безопасно использовать phpass между несколькими серверами? - PullRequest
4 голосов
/ 25 января 2011

С включенным 'portable_hashes'.Я заметил, что по какой-то причине генерируемые им хеши не всегда одинаковы, но всегда возвращаются как действительные, когда передаются через «CheckPassword».Я также заметил, что в генерации хеша используется PHP_VERSION - эти две вещи объединяют меня в беспокойство ... Насколько портативен переносимый?Могу ли я перемещать хеши (сохраненные в пользовательской базе данных) между серверами, Linux, Windows, 64-битными, 32-битными и т. Д. - и при этом проверять их?Что мне нужно сделать, чтобы пароли больше не действовали?

Причина, по которой я спрашиваю, заключается в том, что я использую phpass для паролей в моей среде, которая будет работать на нескольких моих сайтах, многие из которых в настоящее время имеют несколькотысячи пользователей - и были случаи, когда мне приходилось перемещать их на разные серверы и, конечно, обновлять php.Я также могу переключить один или два из Apache, скажем, на lighthttpd или что-то подобное.Излишне говорить, что я чрезвычайно параноик. У меня когда-нибудь будет кошмар поддержки, и я не смогу исправить его каким-либо иным способом, кроме рассылки новых паролей всем (что звучит действительно небезопасно).

Если есть хоть малейшая вероятность того, что пароли когда-либо станут недействительными, - какие шаги я должен предпринять, чтобы создать свой собственный генератор хэшей паролей?Я уже использую 16-байтовую случайную соль (для каждого пользователя), и кроме этого единственной проблемой является растяжение - верно?

Ответы [ 2 ]

8 голосов
/ 25 января 2011

В зависимости от версии PHP, вам не нужно иметь переносимые хэши. На PHP 5.3 и выше, PHP предоставляет свою собственную реализацию bcrypt, если она недоступна в системе. Если на всех ваших серверах установлен PHP 5.3 и выше, я настоятельно рекомендую отключить переносимые хеши. PHPass "переносимые хеши" существует, поскольку в зависимости от установленной версии PHP bcrypt может быть недоступен.

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

Кроме того, PHPass использует PHP_VERSION во время генерации этих хэшей *, чтобы проверить, поддерживает ли функция md5(), доступная в этой версии, параметр $rawMode. Если это не так, pack() используется для преобразования шестнадцатеричных данных в двоичные (обратите внимание, что это значительно медленнее, чем просто использование $rawMode, именно поэтому ветвь сделана).

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

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

* Строка 131


РЕДАКТИРОВАТЬ: Для более подробного объяснения, вот как генерируются хеши в переносном режиме (упрощенный, не использует фактические переменные, найденные в PHPass, но точные). Обратите внимание, что PHPass использует собственную версию кодировки base64.

  1. $final = '$P$'

  2. $final .= encode64_int($rounds) (от конструктора, минимум 5 на PHP 5+, 3 других)

  3. $final .= genSalt() (Солт 6 байтов ... 8 байтов в формате "encode64").

  4. $hash = md5($salt . $password)

  5. Для 2$rounds раз, делайте $hash = md5($hash . $password)

  6. $final = encode64($hash)

Итак, последний хеш по сути таков:

$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0
\__________/\____________________/
  \                   \
   \                   \ Actual Hash
    \
     \  $P$   9   IQRaTwmf
        \_/   \   \______/
         \     \      \
          \     \      \ Salt
           \     \ 
            \     \ # Rounds (not decimal representation, 9 is actually 11)
             \
              \ Hash Header
1 голос
/ 25 января 2011

Единственное использование, которое я вижу для PHP_VERSION, находится в этой строке:

$output .= $this->itoa64[min($this->iteration_count_log2 +
    ((PHP_VERSION >= '5') ? 5 : 3), 30)];

Теперь все, что говорит, это определение максимального количества итераций.И это в методе gensalt_private, который генерирует соли.Так что это произойдет только при сохранении нового пароля и генерации соли.Таким образом, все ранее полученные соли являются переносимыми на 100%.Так что с этим вообще нет проблем с переносимостью ...

Что касается остальных, то, пока вы используете достаточно свежую версию php (5.0+), у вас не должно быть никакой переносимостипроблема вообще, насколько я могу судить (так как функция hash встроена) ...

...