После чтения о хешировании пароля солей я хотел бы реализовать простую версию для администраторской области на сайт, который я создаю.
Если у Вас есть какие-либо хорошие ссылки с кодом, которые реализовали эту идею хорошо, я ценил бы его, если Вы могли бы совместно использовать.
Спасибо,
Процесс регистрации: Пользователь вводит пароль. Система генерирует значение соли из случайных данных (это может быть хэш времени и PID или что-то еще). Система генерирует хэш-значение пароля и значения соли и сохраняет их в регистрационной таблице.
Процесс входа в систему: Пользователь вводит пароль. Система извлекает значение соли из базы данных, хэширует его и пароль и сравнивает с хэшированным значением пароля, введенным в базу данных при регистрации.
Пароль в открытом виде никогда не хранится в базе данных. Значение соли никогда не видно клиенту.
Есть много способов создать солевую нить, но я думаю, вам не нужно много думать о силе соли.
Я хэширую такие пароли
$hash = sha1(strlen($password) . md5($password) . $salt);
Я считаю, что это лучшая производительность между скоростью и «безопасностью».
function salt($lenght = 9) {
$numbers = '0123456789';
$chars = 'qwertzuiopasdfghjklyxcvbnm';
$password = '';
$alt = time() % 2;
for ($i = 0; $i < $length; $i++) {
if ($alt == 1)
{
$password .= $chars[(rand() % strlen($chars))];
$alt = 0;
} else
{
$password .= $numbers[(rand() % strlen($numbers))];
$alt = 1;
}
}
return $password;
}
У меня нет ссылки на доступный код, но в прошлом я делал так: генерировал рандомизированную соль - $salt = rand(1,1000000000);
- и сохранял ее в сессии. Я передаю эту соль на страницу входа в систему и затем использую JavaScript для создания SHA-хэша из соли + пароля, который отправляется вместо пароля в открытом виде. Поскольку соль хранится в сессии, я могу использовать ее, чтобы проверить, совпадает ли хэш логина с хэшем соли + пароля, хранящимся в базе данных.
Не могли бы вы использовать встроенную crypt (...)
функцию ?
... Использование ...
crypt('rasmuslerdorf', '$1$rasmusle$')
... Результат ...
MD5: $1$rasmusle$rISCgZzpwk3UhDidwXvin0
... Другие примеры и другие методы хеширования доступны в документации .
Что ж, вот что я бы сделал:
function makeToken($length = 16) {
if ($length > 16) {
$ret = '';
while ($length > 0) {
$ret .= makeToken(16);
$length -= 16;
}
if ($length < 0) {
$ret = substr($ret, 0, $length);
}
return $ret;
}
$stub = '';
for ($i = 0; $i < 100; $i++) {
$stub .= chr(mt_rand(1, 254));
}
$hash = sha1($stub);
$hashLen = strlen($hash);
$ret = '';
for ($i = 0; $i < $length; $i++) {
$ret .= $hash[mt_rand(0, $hashLen - 1)];
}
return $ret;
}
function makeSaltedHash($string, $salt = '') {
if (empty($salt)) {
$salt = makeToken();
}
$hash = '';
for ($i = 0; $i < 200; $i++) {
$hash = sha1($hash . $salt . $string);
}
return $hash . ':' . $salt;
}
function verifySaltedHash($string, $hash) {
if (strpos($string, ':') === false) return false;
list ($base, $salt) = explode(':', $hash);
$test = makeSaltedHash($string, $salt);
return $test === $hash;
}
Рациональное значение таково:
Во-первых, сгенерируйте случайную соль (она всегда будет возвращать шестнадцатеричную строку, поэтому ее можно использовать для токены и т. д.). Затем переберите функцию хеширования (в данном случае sha1) более 1 раза. Это сделано для того, чтобы создать радужную таблицу (в 200 раз дороже в данном случае), при этом добавляя относительно небольшие затраты на генерацию.
Использование:
Чтобы сгенерировать хэш:
$hash = makeSaltedHash($password);
Чтобы проверить хэш:
$bool = verifySaltedHash($password, $savedHash);
Чтобы сгенерировать токен (защита CSRF, session_id и т. Д.), Вы можете сделать это несколькими способами:
Фиксированная длина :
$token = makeToken(32);
Случайная длина:
$token = makeToken(mt_rand(64,128));
Редактировать: Увеличено количество повторений на sha1 в функции хеширования.
function encodePwd($salt, $string) {
return sha1( $salt . $string );
}
хотя бы на минутку подумайте о рандомизации соли. Специальная кодировка пароля.
Если у меня есть соль «случайный» и пароль «сложный», мой sha1 будет
e55ec45f2873a04d2b888a5f59dd3f9d3bb25329
, который хранится в базе данных. Я хочу проверить это.
Поэтому, когда пользователь предоставляет мне «сложный» в качестве пароля, я помечаю перед ним «случайный» и кодирую его, чтобы получить тот же хеш. Если они равны, то bazinga! я готов.
Но что, если это было случайным образом?
соль, когда она была сохранена: "random"
SHA1: e55ec45f2873a04d2b888a5f59dd3f9d3bb25329
соль, когда пользователь вставил ее: "яблоко"
SHA1: e07b207d77a0bd27d321552fc934b186559f9f42
как я собираюсь сопоставить их?
Если вы ищете более безопасный метод, используйте данные, которые у вас есть , и это константа , например, имя пользователя или идентификатор пользователя или что-то в этом роде (желательно то, что не изменится). Вам нужен узор, на который можно положиться.
имя пользователя будет работать хорошо (вам нужно будет обновить пароль, если они когда-либо изменили имя пользователя), тогда аутентификация может выглядеть как
`WHERE `username` = '&username' AND `password` = '" . encodePwd( $username, $password ) . "'"`
function encodePwd( $username, $password) {
// maybe modify username on a non-random basis? - like
// $username = sha1( substr($username, 2)); // assuming usernames have a min-length requirement
return sha1( $username . $password ) ;
}
Если вам нужны действительно безопасные хэши, используйте Portable PHP-фреймворк .
Я также порекомендовал бы эту статью Месяц безопасности PHP , которая подробно рассматривает хеширование паролей и безопасность хэшей.
код прост, и Дэн Хеберден уже предоставил его.
соль - это просто кусок текста, который вы добавляете или добавляете к паролю перед генерацией хэша. например, если ваш пароль - «пароль», а соль - «соль», тогда хеш будет иметь вид hashFunction ('saltpassword')
вместо hashFunction ('пароль')
.
соли обычно используются, чтобы избежать взлома паролей "радуга" - именно здесь большой список паролей и их хэшей сравнивается с хешированным паролем. Например, в приведенном выше примере, скажем, существует хэш 123456, который соответствует hashFunction ('пароль')
, если злоумышленник знает, что ваш хеш равен 123456, то он знает, что ваш пароль - 'пароль'.
ваша соль должна быть случайной цепочкой букв и цифр - например, kjah !! sdf986. очень маловероятно, что у кого-то будет радужная таблица, включающая kjah !! sdf986password, поэтому даже если кто-то получит ваш хешированный пароль, это будет бесполезно.
однако очевидно, что вам нужно каждый раз использовать одну и ту же соль или, по крайней мере, хранить соль и пароль. потому что, если вы выбираете случайную соль каждый раз, скорее всего, ваш хешированный соль + пароль не будут одинаковыми: D