Шифрование можно делать многократно, вдобавок, подмешивая какую-либо дополнительную информацию, характерную (и главное - постоянную) для конкретного пользователя и/или сервера.
Пример ниже - фрагмент кода SMF. На нем видно, какое разнообразие шифрования паролей только не делают. Родной для SMF метод - шифрование sha1 у клиента (JavaScript), а если этот метод не доступен, то отсылает класически - открытым текстом. Фрагмент кода начинается после того, как уже сделаны проверки для "родных" для SMF методов авторизации и делается попытка обработать пароль иначе (зачем - не знаю).
// Bad password! Thought you could fool the database?!
if ($user_settings['passwd'] != $sha_passwd)
{
// Maybe we were too hasty... let's try some other authentication methods.
$other_passwords = array();
// None of the below cases will be used most of the time (because the salt is normally set.)
if ($user_settings['passwordSalt'] == '')
{
// YaBB SE, Discus, MD5 (used a lot), SHA-1 (used some), SMF 1.0.x, IkonBoard, and none at all.
$other_passwords[] = crypt($_REQUEST['passwrd'], substr($_REQUEST['passwrd'], 0, 2));
$other_passwords[] = crypt($_REQUEST['passwrd'], substr($user_settings['passwd'], 0, 2));
$other_passwords[] = md5($_REQUEST['passwrd']);
$other_passwords[] = sha1($_REQUEST['passwrd']);
$other_passwords[] = md5_hmac($_REQUEST['passwrd'], strtolower($user_settings['memberName']));
$other_passwords[] = md5($_REQUEST['passwrd'] . strtolower($user_settings['memberName']));
$other_passwords[] = $_REQUEST['passwrd'];
// This one is a strange one... MyPHP, crypt() on the MD5 hash.
$other_passwords[] = crypt(md5($_REQUEST['passwrd']), md5($_REQUEST['passwrd']));
// Snitz style - SHA-256. Technically, this is a downgrade, but most PHP configurations don't support sha256 anyway.
if (strlen($user_settings['passwd']) == 64 && function_exists('mhash') && defined('MHASH_SHA256'))
$other_passwords[] = bin2hex(mhash(MHASH_SHA256, $_REQUEST['passwrd']));
}
// The hash should be 40 if it's SHA-1, so we're safe with more here too.
elseif (strlen($user_settings['passwd']) == 32)
{
// vBulletin 3 style hashing? Let's welcome them with open arms \o/.
$other_passwords[] = md5(md5($_REQUEST['passwrd']) . $user_settings['passwordSalt']);
// Hmm.. p'raps it's Invision 2 style?
$other_passwords[] = md5(md5($user_settings['passwordSalt']) . md5($_REQUEST['passwrd']));
}
// Maybe they are using a hash from before the password fix.
$other_passwords[] = sha1(strtolower($user_settings['memberName']) . addslashes(un_htmlspecialchars(stripslashes($_REQUEST['passwrd']))));
// Whichever encryption it was using, let's make it use SMF's now ;).
if (in_array($user_settings['passwd'], $other_passwords))
{
$user_settings['passwd'] = $sha_passwd;
$user_settings['passwordSalt'] = substr(md5(rand()), 0, 4);
// Update the password and set up the hash.
updateMemberData($user_settings['ID_MEMBER'], array('passwd' => '\'' . $user_settings['passwd'] . '\'', 'passwordSalt' => '\'' . $user_settings['passwordSalt'] . '\''));
}
// Okay, they for sure didn't enter the password!
else
{
// They've messed up again - keep a count to see if they need a hand.
$_SESSION['failed_login'] = @$_SESSION['failed_login'] + 1;
// Hmm... don't remember it, do you? Here, try the password reminder ;).
if ($_SESSION['failed_login'] >= $modSettings['failed_login_threshold'])
redirectexit('action=reminder');
// We'll give you another chance...
else
{
// Log an error so we know that it didn't go well in the error log.
log_error($txt[39] . ' - <span class="remove">' . $user_settings['memberName'] . '</span>');
$context['login_error'] = $txt[39];
return;
}
}
}