🧠 COMPUTER SCIENCE

Как сайт хранит твой пароль, даже не зная его

Когда ты вводишь пароль на любимом сайте, он почти наверняка не сохраняет его буквами. Разбираемся, как сервер проверяет твой пароль, по факту его не зная, — и почему «12345» взломают за доли секунды.

Прямо сейчас твой пароль от любимой игры лежит на чужом сервере — и его там никто не может прочитать. Даже сам сервер. Даже админ, который этот сервер построил. Он впустит тебя завтра, но если ты спросишь его «какой у меня пароль?» — он честно ответит, что не знает. Звучит как фокус с исчезновением, но за ним стоит обычная математика. Называется она хеш-функция, и сейчас ты поймёшь её за пять минут.

Хранить пароль как есть — худшая идея на свете

Допустим, сайт сохранил бы твой пароль прямо в базе данных: username: maxim2010, password: koteia123. Удобно? Для хакера — очень. Базы данных воруют постоянно: достаточно одной дыры в коде, и злоумышленник скачивает целиком таблицу с паролями миллионов людей. А поскольку народ обожает один и тот же пароль на всех сайтах, украв его на каком-нибудь форуме про рыбалку, вор зайдёт и в твою почту, и в соцсети, и в банк.

Поэтому грамотные разработчики придумали хитрость: пароль на сервере вообще не хранится. Хранится его «отпечаток». Как отпечаток пальца — по нему тебя можно опознать, но вырастить обратно живой палец из чернильного оттиска нельзя.

Хеш-функция: мясорубка для текста

Хеш-функция — это математическая мясорубка. Кидаешь в неё любой текст — получаешь строку фиксированной длины из букв и цифр. Главные её свойства:

  • Одинаковый вход — одинаковый выход. Слово privet всегда даёт один и тот же отпечаток.
  • Чуть изменил вход — отпечаток меняется целиком. privet и Privet различаются всего одной заглавной буквой, а отпечатки у них вообще ничем не похожи — будто это два разных слова.
  • Обратно не провернуть. Из фарша котлету не собрать. По отпечатку исходный пароль не восстановить — нет такой формулы.

Давай попробуем руками. Возьмём популярный алгоритм SHA-256 в Python:

import hashlib

parol = "privet"
otpechatok = hashlib.sha256(parol.encode()).hexdigest()
print(otpechatok)
# c78e4d4490... (64 символа, всегда одна и та же длина)

Что бы ты ни скормил — слово из трёх букв или весь текст «Войны и мира» — на выходе ровно 64 символа. Поменяй в пароле хоть одну букву с маленькой на большую — и эти 64 символа станут совершенно другими. Именно эту строку сайт и кладёт в базу вместо твоего пароля.

Тогда как сайт тебя узнаёт при входе?

А вот тут изящно. Сервер не сравнивает пароли — он сравнивает отпечатки. Алгоритм такой:

  • При регистрации ты ввёл privet → сайт посчитал хеш → сохранил только хеш.
  • При входе ты снова вводишь privet → сайт снова считает хеш от того, что ты напечатал.
  • Если новый хеш совпал с тем, что лежит в базе, — значит, пароль тот же. Заходи.

Сервер реально не знает твой пароль. Он знает только отпечаток. Если хакер украдёт базу, он получит горы вот таких 64-символьных строк — а не пароли. На первый взгляд бесполезно. Но есть нюанс.

Почему «12345» — это всё равно катастрофа

Раз обратной формулы нет, хакер действует тупо в лоб: берёт миллионы популярных паролей, считает хеш каждого и сравнивает с украденными. Это называется перебор. Современная видеокарта успевает проверить миллиарды вариантов в секунду — так что 12345, qwerty или password ломаются мгновенно: они в любом хакерском списке на первых строчках. Представь телефонный замок с четырьмя кнопками: если код «0000», его подберут с первой попытки, как бы хитро ни был устроен сам замок.

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

Соль: секретный ингредиент

Как испортить хакеру всю малину? Подсыпать соль. Соль — это случайный набор символов, который сайт приклеивает к твоему паролю перед хешированием. У каждого пользователя соль своя.

import hashlib, os

parol = "privet"
sol = os.urandom(8).hex()          # случайная строка для каждого юзера

otpechatok = hashlib.sha256((sol + parol).encode()).hexdigest()
# в базу кладут и соль, и отпечаток

Теперь даже если двое выбрали одинаковый пароль privet, их отпечатки разные — соль-то у каждого своя. Готовые радужные таблицы становятся бесполезны: их пришлось бы пересчитывать заново под каждую соль отдельно, а это снова те самые миллиарды вычислений. А на практике пароли солят и прогоняют через специально медленные алгоритмы (bcrypt, Argon2), чтобы даже перебор шёл черепашьим шагом. SHA-256 из примера — для наглядности; для реальных паролей берут именно такие медленные функции.

Что с этим делать тебе

Соль и хеши — забота сайта. Но половина защиты на твоей стороне, и тут всё просто:

  • Длина важнее «сложности». Фраза из четырёх случайных слов вроде kit-luna-vafli-grom перебирается дольше, чем P@ss1!, и запоминается легче.
  • Разные пароли на разных сайтах. Утёк один — остальные целы.
  • Менеджер паролей придумает и запомнит всё за тебя — тебе нужно держать в голове один мастер-пароль.

Главная мысль: безопасность пароля — это не магия сайта, а простая математика плюс твоя непредсказуемость. Чем длиннее и случайнее твой пароль, тем больше времени уйдёт на его перебор — а «больше времени» здесь означает миллионы лет вместо одной секунды.

#python#безопасность#пароли#хеши