Расшифровка MD5: можно ли получить пароль из хеша
Расшифровать MD5 нельзя: хеш-функция необратима, из 32 знаков хеша исходную строку не вычислить. Зато «расшифровкой» называют подбор: злоумышленник хеширует миллиарды вариантов и ищет совпадение. Пароль из восьми строчных букв и цифр видеокарта RTX 4090 перебирает целиком за 17 секунд. Ниже – как устроен MD5, почему он не годится для паролей, чем его заменить и как перевести действующую базу без массового сброса паролей.
Можно ли расшифровать MD5
Причина проста: функция сжимает вход любой длины до 128 бит и отбрасывает всё лишнее. Вернуть отброшенное нечем.
Шифрование и хеширование – разные операции. Шифрование обратимо: с ключом вы получаете исходный текст. У хеширования нет ни ключа, ни обратного хода. Поэтому «расшифровка пароля» и «зашифрованный хеш» – неверные термины: пароль хешируют, а не шифруют.
Что же делают сервисы с вывеской «расшифровка MD5»? Они подбирают строку. Кто-то считает MD5 от кандидата и сравнивает с вашим хешем. Совпало – прообраз найден. Не совпало – берут следующего кандидата. Кандидатов миллиарды: слова из словарей, утёкшие пароли, все короткие комбинации символов.
Поэтому слово «расшифровка» в этой статье стоит в кавычках. Это обиходное название подбора, а не описание операции. Для вашего проекта из этого следуют три вывода.
- Простые пароли раскрываются сразу. Хеши слов вроде «admin» давно лежат в готовых базах, и найти их – один запрос.
- Длинные случайные пароли держатся дольше. Каждый лишний символ умножает работу перебора на размер алфавита. Но надеяться на выбор пользователя нельзя: хранение должно защищать и слабые пароли.
- Соль и повторный MD5 главного не лечат. Скорость перебора остаётся огромной, цифры – в разделе про взлом.
Хранить пароли в MD5 больше нельзя. Чем заменить алгоритм и как не сбросить пароль каждому пользователю – в разделах про bcrypt, Argon2id и миграцию базы. Сначала разберём, что такое MD5.
Что такое MD5 и как он устроен
Хеширование превращает данные любой длины в строку фиксированной длины. Результат называют хешем, хеш-суммой или хеш-кодом – это одно и то же. Одинаковый вход всегда даёт одинаковый хеш. Поэтому сайт хранит хеш вместо пароля: при входе он хеширует введённое и сравнивает результаты. Идея верная, ошибка – в выборе функции.
MD5 разработал Рон Ривест в 1991 году, а описание вышло в 1992 году как RFC 1321. Алгоритм принимает сообщение любой длины и выдаёт «отпечаток» в 128 бит.

Длина выхода: 128 бит, 16 байт, 32 знака
Считаем один раз и без путаницы. Хеш MD5 занимает 128 бит. В байте 8 бит, значит, хеш весит 16 байт. Один шестнадцатеричный знак (0–9 и a–f) кодирует 4 бита, поэтому 128 ÷ 4 = 32 знака.
| Единица | Размер хеша MD5 |
|---|---|
| Биты | 128 |
| Байты | 16 |
| Шестнадцатеричные знаки | 32 |
Лавинный эффект
Лавинный эффект – свойство хорошей хеш-функции. Вы меняете один символ во входных данных, и хеш меняется целиком, а не в одном месте. Проверьте на двух строках, которые различаются одной буквой.
<?php
echo md5('hello') . "\n";
echo md5('Hello') . "\n";Скрипт выведет два хеша:
5d41402abc4b2a76b9719d911017c592
8b1a9953c4611296a827abf8c47804d7Общего у них нет. Из-за этого по хешу нельзя понять, насколько близки исходные пароли: «password1» и «password2» дают несвязанные хеши. Значит, подобрать пароль «по соседству» нельзя – остаётся перебор.
Почему MD5 больше нельзя использовать для паролей
Настоящая причина: практические коллизии
Коллизия – это два разных входа с одинаковым хешем. Они есть у любой хеш-функции: входов бесконечно много, а хешей конечное число. Плохой функцию делает другое: коллизию удаётся построить быстрее, чем перебором.
Отказ от MD5 связан не с «малой длиной хеша», а с работающими атаками. В 2004 году группа Ван Сяоюнь показала способ находить коллизии полного MD5. В 2007 году Марк Стивенс с соавторами описал chosen-prefix collision: по двум заданным началам файлов подбирают хвосты, после которых хеши совпадают.
Дальше пошла практика. В 2012 году авторы вредоносной программы Flame подделали коллизионной атакой сертификат подписи кода для Windows Vista и новее. Microsoft разобрала эту атаку в блоге MSRC 6 июня 2012 года и назвала её chosen-prefix collision attack.
Что сказано в стандартах
RFC 6151 (март 2011 года) прямо пишет: MD5 больше не приемлем там, где нужна стойкость к коллизиям, например в цифровых подписях. Поэтому в подписях и сертификатах его не используют.
Почему для паролей главное – не коллизии
Коллизии бьют по подписям и сертификатам. Пароль защищают от другого: злоумышленник ищет прообраз одного конкретного хеша. Здесь опаснее скорость. MD5 создан быстрым, а быстрая функция помогает тому, кто перебирает. Цифры – в следующем разделе.
Итог такой: MD5 нельзя для паролей, подписей и сертификатов. В паролях его губит скорость, в подписях и сертификатах – коллизии.
Как на самом деле «взламывают» MD5
Готовые базы и радужные таблицы
Радужная таблица – сжатая база заранее посчитанных хешей. Злоумышленник один раз тратит время на расчёт, а потом ищет ваш хеш в таблице, как слово в словаре. Поиск по готовой базе занимает время запроса, а не перебора.
Онлайн-«декодеры»: что это такое
Онлайн-«декодер» не расшифровывает ничего. Это поиск по базе пар «строка → хеш». Сервис md5.web-max.ca прямо пишет, что ищет хеши по нескольким радужным таблицам. Простые пароли в такой базе есть. Длинные, случайные и солёные – нет.
Вводить в такие формы чужие хеши не стоит: вы передаёте хеши пользователей третьей стороне, а взамен получаете шанс найти только слабые пароли.
Перебор на видеокарте
Главная угроза – прямой перебор. Встроенный тест hashcat (версия 6.2.6, 2022 год) показал на RTX 4090 скорость 164,1 млрд хешей MD5 в секунду. На RTX 5090 тест 2025 года даёт 220,6 млрд в секунду. Это чистая скорость на одном хеше, в реальной атаке она может быть чуть ниже.
| Несолёный пароль из 8 знаков | Вариантов | RTX 4090 | RTX 5090 |
|---|---|---|---|
| Строчные латинские буквы и цифры (36 символов) | 2,8 трлн | 17 секунд | 13 секунд |
| Все 95 печатаемых символов ASCII | 6,6 квадрлн | 11 ч 14 мин | 8 ч 21 мин |
Это полный перебор, то есть худший случай: в среднем пароль находится за половину времени. Даже сложный восьмизнаковый пароль в MD5 не переживёт и суток работы одной видеокарты.
Что делает соль и чего не делает
Соль – случайная строка, которую добавляют к каждому паролю перед хешированием. Она ломает готовые базы: у двух пользователей с одним паролем хеши разные, а заранее посчитать хеш с неизвестной солью нельзя. Но от перебора соль не защищает: она лежит рядом с хешем, и злоумышленник подбирает пароль под каждую запись на той же скорости.
Так делать нельзя: пример из старых руководств, где соль строится через rand().
<?php
$pass = 'admin';
function salt() {
$s = '';
$length = rand(7, 12);
for ($i = 0; $i < $length; $i++) {
$s .= chr(rand(33, 126));
}
return $s;
}
echo md5(md5($pass) . salt());У примера две беды. Первая: MD5 быстр, значит, перебор остаётся дешёвым. Вторая хуже: соль случайна и нигде не сохранена. При следующем входе salt() вернёт другую строку, хеш не совпадёт, и проверить пароль будет невозможно.
Чем заменить MD5 при хранении паролей
Что советует OWASP
Для паролей нужна функция, которая нарочно медленная и жадная до памяти. Password Storage Cheat Sheet называет первым выбором Argon2id: минимум 19 МиБ памяти, 2 итерации и параллелизм 1. Если Argon2id недоступен, берите scrypt с N=2^17 (128 МиБ), r=8, p=1. Остальные алгоритмы OWASP оставляет под особые условия. PBKDF2-HMAC-SHA256 на 600 000 итераций и больше нужен, когда требуется соответствие FIPS-140. Bcrypt со стоимостью не меньше 10 – для унаследованных систем.
Параметры алгоритмов меняются. Перед внедрением сверьтесь с текущей версией OWASP Password Storage Cheat Sheet: цифры в статье приведены на 2026 год и служат минимумом, а не потолком.
| Алгоритм | Год | Длина выхода | Для паролей | Настраиваемая стоимость | Рекомендация |
|---|---|---|---|---|---|
| MD5 | 1992 (RFC 1321) | 128 бит, 32 знака | Нет | Нет | Не использовать для паролей, подписей и сертификатов |
| SHA-256 | 2001 | 256 бит, 64 знака | Нет, слишком быстрый | Нет | Контрольные суммы; для паролей – только внутри PBKDF2 |
| bcrypt | 1999 | Строка из 60 знаков в PHP | Да | Да, коэффициент стоимости | Для унаследованных систем; пароль до 72 байт |
| Argon2id | 2015 (победитель конкурса Password Hashing Competition) | Настраивается | Да | Да: память, итерации, параллелизм | Первый выбор OWASP |
Код на PHP: password_hash и password_verify
В PHP всё готово в трёх функциях. Соль password_hash() генерирует сам и кладёт внутрь возвращаемой строки. Отдельная колонка под соль не нужна, а прежний параметр salt с PHP 8.0 игнорируется.
<?php
// при регистрации или смене пароля
$hash = password_hash($password, PASSWORD_DEFAULT);
// при входе
if (password_verify($password, $hash)) {
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
$hash = password_hash($password, PASSWORD_DEFAULT);
// обновите запись пользователя
}
// впустите пользователя
}Сейчас PASSWORD_DEFAULT равна PASSWORD_BCRYPT. В PHP 8.4 стоимость bcrypt по умолчанию выросла с 10 до 12. Bcrypt усекает пароль до 72 байт, поэтому ограничьте длину пароля на форме. Строка bcrypt занимает 60 знаков, но документация PHP советует колонку на 255 знаков: результат со временем может вырасти. Вызов password_needs_rehash() заметит, что параметры устарели, и вы обновите хеш при ближайшем входе.
Выбор у password_hash() небольшой: bcrypt и Argon2 (PASSWORD_ARGON2I, PASSWORD_ARGON2ID). Scrypt и PBKDF2 в эту функцию не входят. Argon2id доступен, только если PHP собран с поддержкой Argon2. Проверьте это на своём хостинге раньше, чем менять код. Нет Argon2 – берите bcrypt: в PHP это самый практичный запасной путь.
Как перевести существующую базу паролей на новый алгоритм
Пароли в MD5 пересчитать сразу нельзя: их исходных значений в базе нет. Схема простая: пересчитываем каждый пароль в момент входа, когда пользователь сам его вводит. Для остальных есть запасной путь. Всего четыре шага.
Шаг 1. Добавьте колонки
Оставьте старую колонку с MD5 и заведите две новые: под новый хеш и под версию алгоритма.
ALTER TABLE users
ADD COLUMN pass_hash VARCHAR(255) NULL,
ADD COLUMN hash_version TINYINT NOT NULL DEFAULT 1;Версия 1 – старый MD5, версия 2 – новый хеш самого пароля, версия 3 – новый хеш поверх старого MD5.
Умолчание 1 подходит только старым записям. Новых пользователей и смену пароля пишите сразу с версией 2. Иначе новичок попадёт в ветку MD5, где pass_md5 пуст, и войти не сможет.
<?php
function register(string $login, string $pass): void {
// версию 2 указываем явно: умолчание колонки (1) для новых записей не годится
insert_user($login, password_hash($pass, PASSWORD_DEFAULT), 2);
}Шаг 2. Пересчитывайте пароль при входе
При успешном входе проверьте пароль по старой схеме, затем сразу сохраните новый хеш и сотрите MD5. Функция save_hash() в примере записывает pass_hash, ставит версию 2 и обнуляет pass_md5.
<?php
function login(array $row, string $pass): bool {
if ($row['hash_version'] == 1) {
// старая запись: MD5 лежит в pass_md5
if (!hash_equals((string) $row['pass_md5'], md5($pass))) {
return false;
}
} elseif ($row['hash_version'] == 3) {
// обёртка из шага 3
if (!password_verify(md5($pass), $row['pass_hash'])) {
return false;
}
} else {
if (!password_verify($pass, $row['pass_hash'])) {
return false;
}
if (!password_needs_rehash($row['pass_hash'], PASSWORD_DEFAULT)) {
return true;
}
}
// пересчёт: новый хеш самого пароля, MD5 стирается
save_hash($row['id'], password_hash($pass, PASSWORD_DEFAULT));
return true;
}Шаг 3. Разберитесь с теми, кто не заходит
Активные пользователи мигрируют сами. Остальные годами будут хранить MD5. OWASP описывает два пути. Первый – обернуть старый хеш новым алгоритмом: bcrypt(md5($password)). Скрипт проходит по записям порциями, MD5 в базе исчезает сразу.
<?php
// для каждой записи с hash_version = 1
$wrapped = password_hash($row['pass_md5'], PASSWORD_DEFAULT);
// сохранить: pass_hash = $wrapped, hash_version = 3, pass_md5 = NULLMD5-хеш занимает 32 знака и укладывается в предел bcrypt в 72 байта. При следующем входе ветка версии 3 из шага 2 заменит обёртку прямым хешем пароля. Второй путь – для давно неактивных: сотрите хеши и потребуйте сброс пароля. Срок неактивности выберите сами.
Шаг 4. Пишите в лог и считайте долю
Записывайте каждый пересчёт: id пользователя, время, версию до и после. Пароль и хеш в лог не пишите никогда. Долю мигрировавших даёт один запрос.
SELECT hash_version, COUNT(*) AS users
FROM users
GROUP BY hash_version;Когда записей с версиями 1 и 3 не осталось, удалите колонку pass_md5. Миграция закончена.
Где MD5 всё ещё уместен
Где он подходит
MD5 остаётся быстрым и удобным там, где никто не подделывает данные.
- Контрольные суммы файлов. Сумма выявляет случайную порчу при скачивании или копировании: файл побился, суммы разошлись.
- Поиск дублей. Утилита fdupes ищет одинаковые файлы, сравнивая размеры и MD5-подписи, а потом побайтово подтверждает совпадение.
- Ключи кеша. Хеш содержимого даёт короткий стабильный ключ. Если два разных входа дадут один ключ, кеш промахнётся, а не пострадает безопасность.
Где его брать нельзя
Подписи, сертификаты и пароли – табу. Документация GNU coreutils прямо предупреждает: MD5 нельзя считать защищённым от злонамеренной подмены, потому что известно, как изменить некоторые файлы, включая сертификаты, чтобы они выглядели валидными при подписи MD5. Нужна защита от подделки – берите SHA-256 или другой стойкий хеш.
Какой хеш выбрать под задачу
- Хранение паролей – Argon2id, а если PHP собран без Argon2, то bcrypt: другого выбора в
password_hash()нет. Пересчитывайте пароли при входе. - Защита файла от подмены – SHA-256, а не MD5.
- Проверка на случайную порчу и поиск дублей – MD5 достаточно.
- Подписи и сертификаты – только стойкий хеш.
Совет от нашей редакции: не меняйте MD5 на голый SHA-256, это всё тот же быстрый перебор, – берите Argon2id или bcrypt и пересчитывайте пароли при входе пользователей.
Комментарии
Последний ресурсу (рускоязычный) не работает, а первых два ничего не дешефруют... Только могут дешифровать то, что записано в их базе, а не тот, что я ввел... Не существует нормального декриптовальщика, шифрование MD5 работает только в одну сторону, что бы его расшифровать, используется только перебор, типа брутфорс.
А почему 16 шестнадцатеричных чисел, разве не 32?
Потому что система счисления
Шестнадцатеричное число означает, что существует всего 16 цифер, к примеру мы пользуемся десятичной системой исчисления (1-9).
Только не 1-9, а 0-9