Преобразовать MD5 в SHA-256? Почему это невозможно и что делать
Такое обещают десятки страниц, и часть из них выглядит как вполне рабочие инструменты. Операции, которую они рекламируют, не существует, а от причины зависит, что вам делать дальше.
Короткий ответ: MD5 в SHA-256 не преобразуется (и SHA-256 в MD5 тоже)
Преобразовать хеш MD5 в SHA-256 нельзя. Дайджест MD5 — это 128 бит вывода, внутри которых нет породивших его входных данных. А SHA-256 эти данные нужны, иначе он не вычислит вообще ничего. Без исходных данных промежуточное звено взять неоткуда, и ни один инструмент или библиотека его не восстановит.
Вот один и тот же ввод под тремя алгоритмами:
| Алгоритм | Дайджест строки hello | Символов hex | Бит |
|---|---|---|---|
| MD5 | 5d41402abc4b2a76b9719d911017c592 | 32 | 128 |
| SHA-1 | aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d | 40 | 160 |
| SHA-256 | 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 | 64 | 256 |
Как строки эти три дайджеста между собой не связаны: ни общего префикса, ни общей подстроки, и никакая арифметика не переводит один в другой. Единственное, что их объединяет, — слово hello, и ни один из них его в себе не несёт. Вычислите их сами в генераторе MD5-хешей и генераторе SHA-256, если хотите увидеть, как оба меняются независимо друг от друга прямо по мере набора текста.
Направление ничего не меняет. Путь от SHA-256 к MD5 обрывается ровно по той же причине: обе функции уничтожают информацию намеренно, поэтому ни один дайджест не отматывается назад к тому вводу, который понадобился бы второй функции.
Зато есть вопрос по существу: из любопытства к теории хеширования такой запрос никто не набирает, значит, требовалось сделать что-то конкретное. На практике это одна из четырёх задач, и у каждой есть настоящий ответ:
- Проверка загруженного файла или сверка контрольных сумм
- Перевод базы паролей с MD5 на что-то другое
- Восстановление исходных данных, стоящих за хешем
- Получение тех же данных, посчитанных другим алгоритмом
К каждой вернёмся ниже. Но сначала стоит разобрать, как устроены страницы с обещанием преобразования: после этого доверять их выводу уже не получится.
Что на самом деле делает страница «конвертер MD5 в SHA-256»
Такая страница может делать одно из трёх, и преобразования среди этих трёх нет.
Она просит у вас исходный текст. Вы вставляете строку, страница выдаёт оба дайджеста, а рекламный текст называет это преобразованием. Перед вами генератор хешей с обманчивой подписью. Ничего не преобразовано; для одного и того же ввода хеш просто посчитали дважды.
Она ищет дайджест по таблице. Страница держит таблицу пар «ввод — дайджест», собранную из словарей и утёкших дампов учётных данных. Вставьте MD5, чей ввод есть в этой таблице, — страница найдёт ввод, вычислит от него SHA-256 и покажет результат. Это работает для password, 123456 и длинного хвоста других коротких строк. На всём остальном оно молча отказывает — потому такие страницы часто возвращают пустой результат без всяких объяснений.
А иногда она не делает вообще ничего. Удивительно много таких страниц просто показывают ваш ввод обратно или выдают SHA-256 от вставленной шестнадцатеричной строки и подписывают его как SHA-256 ваших исходных данных. Это два разных значения, и раздел о двойном хешировании ниже показывает, насколько разных.
Проверка занимает секунду. Дайте странице 32-символьную шестнадцатеричную строку и больше ничего, а затем спросите себя, могла ли она вообще узнать исходные данные. Если она всё равно возвращает 64-символьный результат и называет это преобразованием, значит, она либо обращается к таблице подстановки, либо врёт. Конвертер хешей, который никогда не спрашивает исходные данные, может оказаться правым только случайно.
Живуча эта формулировка потому, что рядом есть похожие операции, которые действительно работают. С них путаница и начинается.
Хеширование, кодирование и шифрование: обратимы только два из трёх
Разработчик встречает все три на одной неделе и мысленно складывает их в одну кучу. Ведут они себя совершенно по-разному:
| Операция | Пример | Обратима? | Что нужно |
|---|---|---|---|
| Кодирование | Base64, hex, URL-кодирование | Да, всегда | Ничего |
| Шифрование | AES, RSA | Да | Ключ |
| Хеширование | MD5, SHA-1, SHA-256 | Никогда | Ничто не поможет |
Неверную интуицию задаёт как раз Base64. Декодировать строку Base64 обратно в байты может кто угодно, без ключа и без разрешения, а перевести Base64 в hex — законная повседневная операция. И то и другое — просто альтернативные написания одних и тех же байтов. После этого «MD5 в SHA-256» звучит как такая же перезапись.
Это не так. Кодирование сохраняет каждый бит ввода, шифрование сохраняет его за ключом, а хеширование почти всё выбрасывает. Дайджест MD5 занимает 16 байт независимо от того, подали вы ему пароль или образ диска на 40 ГБ. Эти 40 ГБ не спрятаны где-то хитрым способом — их просто нет. FAQ инструмента MD5 подробнее разбирает сравнение с шифрованием, если оно нужно, но здесь хватит однострочной версии: ключа нет, а значит, и расшифровывать нечего.
«MD5 сломан» не означает «MD5 обратим»
Здесь ошибаются даже добросовестные статьи: от «MD5 сломали много лет назад» рассуждение сразу перескакивает к «значит, кто-то уже наверняка научился его разворачивать».
Речь о двух разных атаках:
- Атака на коллизию находит два разных входа, дающих один и тот же дайджест. Атакующий выбирает оба входа, и ему безразлично, какими они получатся.
- Атака на прообраз начинается с дайджеста и восстанавливает вход, который его порождает. Именно она позволила бы преобразовать MD5 в SHA-256, потому что вернула бы вам то, что можно подать на вход SHA-256.
Стойкость MD5 к коллизиям пала в 2004 году, и сегодня коллизия собирается на обычном железе за секунды. Поэтому MD5 непригоден для подписей, сертификатов и всего, на что может влиять противник.
Стойкость MD5 к прообразу не пала. Лучшая известная атака на прообраз остаётся теоретической, её сложность — 2^123.4 (Sasaki and Aoki, 2009). Это быстрее полного перебора на волосок, но на практике всё равно недостижимо. Произвольные дайджесты MD5 не обращает никто — ни в 2004 году, ни сейчас.
Так что оба утверждения верны одновременно: MD5 сломан и при этом по-прежнему необратим. На исходный вопрос взлом коллизий не влияет. Если вы выбираете алгоритм для новой системы, а не пытаетесь преобразовать один в другой, этот выбор подробно разбирает сравнение MD5 и SHA-256.
Что вам нужно на самом деле: четыре задачи и настоящий ответ для каждой
| Ваша реальная задача | Что делать |
|---|---|
| Проверяете загруженный файл или сверяете контрольные суммы | Пересчитайте от файла нужным алгоритмом |
| Переносите MD5-хеши паролей | Оберните их в bcrypt и обновляйте при входе |
| Восстанавливаете исходные данные | Это взлом, а не преобразование, и зависит он от энтропии |
| Считаете те же данные другим алгоритмом | Вернитесь к исходным байтам |
Задача 1: вы сверяете контрольные суммы или проверяете загруженный файл
Пересчитайте, а не преобразуйте. Файл лежит у вас на диске, а это и есть то единственное, что дайджест потерял. Прогоните по нему нужный алгоритм:
# GNU coreutils
md5sum ubuntu-24.04-desktop-amd64.iso
sha256sum ubuntu-24.04-desktop-amd64.iso
# macOS
md5 ubuntu-24.04-desktop-amd64.iso
shasum -a 256 ubuntu-24.04-desktop-amd64.iso
Несостыковка, на которую натыкаются люди, — издатель публикует только MD5, тогда как политика безопасности требует SHA-256. Преобразование опубликованного MD5 ничего бы не доказало, даже будь оно возможным: дайджест, выведенный вами из другого дайджеста, ничего не говорит о файле от имени издателя. Нужен SHA-256, который издатель подписал. Если он такого не предлагает, собственный SHA-256, посчитанный в генераторе SHA-256, всё равно даёт стабильный отпечаток для внутреннего использования: его можно зафиксировать, сравнить между зеркалами и позже заметить изменения. Просто он не заменяет свидетельство издателя.
Задача 2: вы переводите базу паролей с MD5
У этой задачи самая высокая цена ошибки, и решение здесь давно известно: обернуть старые хеши, а затем прозрачно обновлять каждую учётную запись при входе. Одним пакетным заданием вы прогоняете все хранимые MD5-хеши через bcrypt, и с этого момента путь входа сначала берёт MD5 от присланного пароля, а затем сверяет полученное с bcrypt-записью.
Одна оговорка, потому что многие старые советы понимают это наоборот: обёртывание MD5 в SHA-256 хранение паролей безопасным не делает. SHA-256 — быстрый хеш, та же категория проблемы, что и MD5: GPU перебирает и то и другое с огромной скоростью. Совет, указывающий на встроенную функцию SHA2() вашей СУБД как на решение, лечит не ту болезнь. Цель — намеренно медленный хеш: bcrypt, scrypt или Argon2. Храните bcrypt(md5(password)), но никогда sha256(md5(password)). Как выбрать между ними, разбирает сравнение bcrypt, Argon2 и scrypt, а генератор bcrypt позволяет опробовать разные cost-факторы, прежде чем остановиться на одном.
Ломаются миграции обычно на другом. «MD5 от пароля» — двусмысленная формулировка, и два её прочтения дают разные результаты:
const { createHash } = require('node:crypto');
const md5Hex = createHash('md5').update('hello').digest('hex');
const md5Raw = createHash('md5').update('hello').digest(); // the same value as 16 bytes
createHash('sha256').update(md5Hex).digest('hex');
// 4914e23374bb211e3dca0df7636fefffc7fedd94f1340ae81c7d6c07b7113e9b
createHash('sha256').update(md5Raw).digest('hex');
// 88e20f0abb88153e3f0a9683668ccb5b84ed771817dc448a2b73254ed02c8d8c
createHash('sha256').update('hello').digest('hex');
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Три результата, все верные, все разные. Возьмите хеш от 32-символьной шестнадцатеричной строки — получите одно значение; от 16 сырых байт, которые она представляет, — другое; от исходного пароля — третье. Выберите соглашение, запишите его и применяйте одно и то же в скрипте миграции и на пути входа. Ошибка здесь блокирует сразу всех пользователей, а выглядит она как баг bcrypt, а не как последствие выбранной кодировки.
Для обёртки в bcrypt безопаснее выбрать hex. Сырые байты дайджеста могут содержать нулевой байт, а некоторые реализации bcrypt считают свой вход C-строкой и на этом месте прекращают чтение. Hex снимает вопрос целиком, а его 32 символа с запасом укладываются в ограничение bcrypt на длину входа. Нормализуйте ещё и регистр: 5D41402A... и 5d41402a... — для bcrypt это разные строки, хотя дайджест один и тот же.
const bcrypt = require('bcrypt');
const { createHash } = require('node:crypto');
const legacyDigest = (password) =>
createHash('md5').update(password, 'utf8').digest('hex'); // lowercase hex
// Batch job, run once: wrap each stored MD5, then drop the old column.
async function wrapRow(row) {
return bcrypt.hash(row.md5_hash.toLowerCase(), 12);
}
// Login path
async function verify(password, row) {
if (row.scheme === 'bcrypt') {
return bcrypt.compare(password, row.hash);
}
const ok = await bcrypt.compare(legacyDigest(password), row.hash);
if (ok) {
const upgraded = await bcrypt.hash(password, 12);
await saveCredential(row.id, { scheme: 'bcrypt', hash: upgraded }); // your DB write
}
return ok;
}
Учётные записи переходят на чистый bcrypt по мере того, как их владельцы заходят в систему. Назначьте срок для отстающих и после него принудительно сбросьте пароли.
Задача 3: вы пытаетесь восстановить исходные данные
Скажите это прямо — хотя бы себе, потому что от этого меняются и инструменты, и ожидания. Восстановление входа из дайджеста — это взлом, а не преобразование, и получится ли оно, никак не зависит от того, каким алгоритмом дайджест получен. Зависит от самого входа.
Короткие и распространённые строки, придуманные человеком, падают быстро. Словарные слова, имена с цифрой на конце и всё, что засветилось в корпусе утечек, сдаются подстановке по таблице или короткому перебору. Длинные случайные строки не падают вовсе, и разрыв между этими двумя случаями не закрывается покупкой железа.
О радужных таблицах стоит сказать точнее, чем обычно говорят. Радужная таблица восстанавливает вход только тогда, когда хеш от него вычислили без соли и сам вход уже присутствует в таблице. Нужны оба условия. Добавьте отдельную соль для каждого пользователя — и предвычисленная таблица обесценится, потому что атакующему понадобилась бы своя таблица под каждую соль. Подайте на вход 128-битное случайное значение — и ни одна таблица на свете его не содержит. Где именно проходит эта граница, с числами разбирает руководство по энтропии паролей.
Если вход был вашим собственным паролем и воспроизвести его не выходит, отнеситесь к этому как к сбросу, а не к восстановлению. Если он принадлежит кому-то другому, честная формулировка приведена выше.
Задача 4: вам нужны те же данные, посчитанные другим алгоритмом («md5 to sha1 converter»)
Та же форма, что и в задаче 1, только обобщённая. Пара алгоритмов в запросе роли не играет, потому что ответ всегда один: вернуться к исходным байтам и вычислить хеш заново:
sha1sum payload.bin
sha256sum payload.bin
Любой найденный «md5 to sha1 converter» — это либо повторный расчёт хеша, либо таблица подстановки, ровно по причинам выше. Если исходные данные недоступны, у задачи нет решения, и это не ограничение доступных инструментов. Выбрать целевой алгоритм поможет сравнение семейства SHA; генератор SHA-1 остаётся для унаследованных систем, которым он всё ещё нужен, хотя ничему новому он требоваться не должен.
Единственный случай, когда поиск по базе у конвертера действительно работает
Некоторые классы данных собирают централизованно и сразу индексируют по всем распространённым дайджестам. Образцы вредоносного ПО — стандартный пример. Сервисы вроде VirusTotal хранят сам образец, поэтому они вычислили его MD5, SHA-1 и SHA-256 от одних и тех же байтов и подшили все три к одной записи. Найдите там образец по MD5 — и получите обратно его SHA-256.
Это соединение таблиц, а не преобразование. Оно работает потому, что у кого-то был исходный файл и он посчитал от него хеши всеми алгоритмами — ровно тот шаг пересчёта, что описан выше, просто выполненный заранее третьей стороной. Условия жёсткие: объект должен уже быть в индексе, а тому, кто индекс построил, придётся доверять. В threat intelligence этим пользуются ежедневно. О произвольных дайджестах MD5 это не говорит ничего и с хешем ваших собственных данных не поможет никогда.
Механизм здесь тот же, что используют сомнительные страницы-конвертеры. Разница в том, что репозиторий вредоносного ПО прямо сообщает, что это поиск по базе, и показывает саму запись.
Попробуйте сами
Проще всего увидеть это на паре команд. Два дайджеста одного и того же ввода меняются вместе, но связи между ними нет:
$ printf 'hello' | md5sum
5d41402abc4b2a76b9719d911017c592 -
$ printf 'hello' | sha256sum
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 -
Измените один символ — и оба вывода изменятся целиком, а предсказать один по другому не выйдет. Вставьте один и тот же текст рядом в генератор MD5-хешей и генератор SHA-256, чтобы увидеть это вживую, или возьмите генератор HMAC, когда на самом деле нужен дайджест на ключе — например, для подписи запроса по API. Все три работают целиком в браузере.
FAQ
Можно ли преобразовать MD5 в SHA-256?
Нет. Дайджест MD5 не содержит исходных данных, а SHA-256 они нужны, чтобы выдать хоть что-нибудь. Любая страница, заявляющая о преобразовании, либо заново считает хеш от предоставленного вами текста, либо ищет значение в базе предвычисленных пар.
Почему так много сайтов предлагает «конвертер MD5 в SHA-256»?
Они ранжируются по запросу, который люди набирают. Попав туда, вы увидите одно из двух: страница либо просит исходный текст (тогда это повторный расчёт, а не преобразование), либо не возвращает ничего полезного. Формулировка живёт, потому что стоящее за ней заблуждение распространено.
Можно ли преобразовать SHA-256 обратно в MD5?
Нет, и направление роли не играет. Обе функции односторонние, поэтому ни один дайджест не превращается в другой без исходных данных. Инструмент, предлагающий обратный путь, крутит тот же трюк с таблицей или повторным расчётом.
MD5 сломан — разве это не значит, что его можно обратить?
Нет. Стойкость MD5 к коллизиям пала в 2004 году: два входа можно заставить сойтись на одном дайджесте. Обращение дайджеста — это атака на прообраз, и лучшая известная по-прежнему стоит 2^123.4 операций. Сломан для подписей, но всё ещё необратим.
Как перевести базу MD5-хешей паролей на что-то более безопасное?
В MySQL напрашивается однострочник UPDATE users SET password = SHA2(password, 256), но он неверен: он берёт хеш от сохранённого дайджеста MD5, а не от пароля. Поэтому храните bcrypt(md5(password)) и проверяйте через ту же обёртку, обновляя каждую запись при следующем успешном входе. Обёртывание MD5 в SHA-256 не помогает: оба алгоритма быстрые, и GPU перебирает варианты для любого из них с огромной скоростью.
Почему двойное хеширование дало не тот результат, которого я ожидал?
Хеш от шестнадцатеричной строки MD5 и хеш от её 16 сырых байт дают разные значения SHA-256. Оба верны — это просто разные входные данные. Выберите одно соглашение и применяйте его одинаково в скрипте миграции и на пути входа.
Может ли радужная таблица восстановить исходные данные по хешу MD5?
Только если хеш вычислен без соли, а сам вход уже присутствует в таблице, — на практике это короткие или распространённые строки. Длинные случайные входы так не восстанавливаются, а отдельная соль для каждого пользователя обесценивает предвычисленные таблицы полностью.
Существует ли конвертер MD5 в SHA-1?
Нет. Любой «конвертер MD5 в SHA-1» — это либо повторный расчёт хеша, либо таблица подстановки: обе функции односторонние, поэтому путь от MD5 к SHA-1 закрыт ровно так же, как путь к SHA-256. Если исходные данные у вас есть, посчитайте дайджест заново в генераторе SHA-1; без них не поможет ничто.