Расшифровка MD5: можно ли получить пароль из хеша

Расшифровать MD5 нельзя: хеш-функция необратима, из 32 знаков хеша исходную строку не вычислить. Зато «расшифровкой» называют подбор: злоумышленник хеширует миллиарды вариантов и ищет совпадение. Пароль из восьми строчных букв и цифр видеокарта RTX 4090 перебирает целиком за 17 секунд. Ниже – как устроен MD5, почему он не годится для паролей, чем его заменить и как перевести действующую базу без массового сброса паролей.

АМ Антон Малаховавтор материала

Можно ли расшифровать MD5

Причина проста: функция сжимает вход любой длины до 128 бит и отбрасывает всё лишнее. Вернуть отброшенное нечем.

Шифрование и хеширование – разные операции. Шифрование обратимо: с ключом вы получаете исходный текст. У хеширования нет ни ключа, ни обратного хода. Поэтому «расшифровка пароля» и «зашифрованный хеш» – неверные термины: пароль хешируют, а не шифруют.

Что же делают сервисы с вывеской «расшифровка MD5»? Они подбирают строку. Кто-то считает MD5 от кандидата и сравнивает с вашим хешем. Совпало – прообраз найден. Не совпало – берут следующего кандидата. Кандидатов миллиарды: слова из словарей, утёкшие пароли, все короткие комбинации символов.

Поэтому слово «расшифровка» в этой статье стоит в кавычках. Это обиходное название подбора, а не описание операции. Для вашего проекта из этого следуют три вывода.

  • Простые пароли раскрываются сразу. Хеши слов вроде «admin» давно лежат в готовых базах, и найти их – один запрос.
  • Длинные случайные пароли держатся дольше. Каждый лишний символ умножает работу перебора на размер алфавита. Но надеяться на выбор пользователя нельзя: хранение должно защищать и слабые пароли.
  • Соль и повторный MD5 главного не лечат. Скорость перебора остаётся огромной, цифры – в разделе про взлом.

Хранить пароли в MD5 больше нельзя. Чем заменить алгоритм и как не сбросить пароль каждому пользователю – в разделах про bcrypt, Argon2id и миграцию базы. Сначала разберём, что такое MD5.

Что такое MD5 и как он устроен

Хеширование превращает данные любой длины в строку фиксированной длины. Результат называют хешем, хеш-суммой или хеш-кодом – это одно и то же. Одинаковый вход всегда даёт одинаковый хеш. Поэтому сайт хранит хеш вместо пароля: при входе он хеширует введённое и сравнивает результаты. Идея верная, ошибка – в выборе функции.

MD5 разработал Рон Ривест в 1991 году, а описание вышло в 1992 году как RFC 1321. Алгоритм принимает сообщение любой длины и выдаёт «отпечаток» в 128 бит.

Логотип MD5 на фоне зелёных столбцов цифр

Длина выхода: 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 4090RTX 5090
Строчные латинские буквы и цифры (36 символов)2,8 трлн17 секунд13 секунд
Все 95 печатаемых символов ASCII6,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 год и служат минимумом, а не потолком.

АлгоритмГодДлина выходаДля паролейНастраиваемая стоимостьРекомендация
MD51992 (RFC 1321)128 бит, 32 знакаНетНетНе использовать для паролей, подписей и сертификатов
SHA-2562001256 бит, 64 знакаНет, слишком быстрыйНетКонтрольные суммы; для паролей – только внутри PBKDF2
bcrypt1999Строка из 60 знаков в PHPДаДа, коэффициент стоимостиДля унаследованных систем; пароль до 72 байт
Argon2id2015 (победитель конкурса 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 = NULL

MD5-хеш занимает 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?

Е
Евгений

Потому что система счисления

IE
Ilya E.

Шестнадцатеричное число означает, что существует всего 16 цифер, к примеру мы пользуемся десятичной системой исчисления (1-9).

F
fr7stzz
➞ Ilya E.

Только не 1-9, а 0-9