Как по строке хеша отличить схему: практическая процедура
· Обновлено: · Го Комура · Хеш, Безопасность, Пароли, Повторное использование существующих активов, Техническое расследование
История изменений (2 обновлений, последнее 30 Aug 2026)
Журнал изменений этой статьи. Там, где версия до правки была заархивирована, она остаётся доступной для чтения по постоянной ссылке с DOI.
- Переведены названия источников в списке литературы. Утверждения статьи не менялись.
- Русский текст переписан как полноценный технический перевод, а не калька с японского. Утверждения статьи не менялись.
- Первая публикация
Цитирование статьи(DOI (зарегистрированный архив): 10.5281/zenodo.21619828)
Приведённые ниже DOI относятся к ранее зарегистрированным архивным версиям, которые могут отличаться от текущего текста. Для ссылки на текущий текст используйте URL этой страницы.
Го Комура (2026). Как по строке хеша отличить схему: практическая процедура. KomuraSoft LLC. https://comcomponent.com/ru/blog/2026/04/10/000-hash-format-identification/
- DOI (зарегистрированный архив)
- 10.5281/zenodo.21619828
- DOI (последняя зарегистрированная версия)
- 10.5281/zenodo.21619829
Часто смотришь на строку вроде 5f4dcc3b5aa765d61d8327deb882cf99 или $2b$12$... в логах или БД и хочешь понять: «это хеш чего?» При миграции существующих систем, разборе метода аутентификации, анализе логов, интеграции со сторонней системой дело нередко упирается именно сюда.
Опасность здесь — сразу решать только по длине.
Увидеть 64 hex-символа и сказать «это SHA-256» — слишком рано. Ту же длину дают стандартный 32-байтовый вывод SHA3-256, SHA-512/256, BLAKE2s-256, BLAKE3. Наоборот, форматы хранения, в которых есть префикс и параметры — $2b$, $argon2id$ и им подобные — по одной строке определяются довольно точно.
В этой статье слово hash берём широко: не только message digest вроде MD5 / SHA-2 / SHA-3, но и строковые представления для хранения паролей — bcrypt / scrypt / Argon2 / PBKDF2.
Материал собран по официальным источникам, доступным на апрель 2026 года: RFC, NIST, Linux crypt(5), Apache, Django, Spring Security и другие.
Статья рассчитана на тех, кто занимается миграцией существующих систем, разбором аутентификации или анализом логов и хочет отличить, что за «хешеподобная строка» лежит перед ним. Достаточно понимать, что такое шестнадцатеричная запись и Base64.
Процедуру из статьи применяйте только к строкам из среды, которой вы управляете, или из среды, где расследование явно разрешено. Доставать хеши паролей чужих учётных записей или разбирать хеши системы, к которой нет прав, нельзя оправдать даже целью расследования. Команды проверки в конце статьи предполагают тестовую учётную запись или образец, который вы сделали сами.
Содержание
- Сначала вывод
- Таблица определения с первого взгляда
- Практический порядок определения
- Частые ошибки определения
- Порядок проверки, если нужна стопроцентная уверенность
- Итог
- Услуги, связанные с этой темой
- Источники
На схеме сплошная линия обозначает отношение, которое выполняется всегда, а пунктирная — условное отношение (условия указаны в пояснении к каждому отношению на странице сведений). Полный список отношений (всего 27, с доказательствами и степенью уверенности) и определения основных понятий собраны на странице сведений карты знаний (на японском). Данные: JSON-LD / Turtle
1. Сначала вывод
Коротко, до деталей.
-
Форматы хранения с префиксом или разделителями по одной строке определяются довольно точно. Примеры:
$argon2id$...,$2b$...,$5$...,$6$...,{SHA}...,pbkdf2_sha256$... -
Обычная шестнадцатеричная строка или просто Base64 обычно дают только «сузить круг кандидатов». Пример:
32 hex = возможно MD5, но не исключены MD4 или NT-хеш -
Набор символов важен не меньше длины. Есть
+/=— похоже на Base64 по RFC 4648; есть.и разделитель$— похоже на семействоcrypt(3). Такие признаки реально работают. -
Для стопроцентной уверенности нужен контекст.
/etc/shadow,.htpasswd,auth_userв Django или Spring Security — это разные истории.
Иными словами, «схемы, которые можно определить по одной строке» и «схемы, где строка даёт только круг кандидатов» — разные вещи. Уже одно это разделение меняет ход расследования.
2. Таблица определения с первого взгляда
Перед таблицей зафиксируем четыре названия «форматов», которые дальше встречаются рядом, но означают разное.
| Термин | Полная форма | Что обозначает |
|---|---|---|
crypt(3) |
- | Сама функция хеша пароля в Unix. Имя функции библиотеки C; так пишут, потому что она в главе 3 man (библиотечные функции) |
crypt(5) |
- | Страница man про строковый формат, который эта функция читает и пишет. Глава 5 man (форматы файлов); запись вида $6$salt$hash описана именно здесь |
| MCF | Modular Crypt Format | Разговорное имя записи «в начале ставят $id$ и этим показывают схему». Отдельной спецификации нет: название закрепилось как соглашение, пока росло число реализаций семейства crypt(3) |
| PHC string format | Password Hashing Competition string format | Спецификация, которая заново упорядочила MCF. Задаёт даже запись версии и параметров, например $argon2id$v=19$m=65536,t=3,p=4$salt$hash |
Грубо: crypt(3) — функция, crypt(5) — спецификация её выходного формата, MCF — разговорное имя этого формата, PHC string format — его же письменная спецификация. Когда в таблицах ниже написано «PHC string format» или «семейство crypt», читайте в этом смысле.
2.1 То, что почти однозначно определяется по префиксу или маркеру формата
«Уверенность» в таблице значит следующее.
- Высокая: почти можно определить только по строке
- Средняя: круг кандидатов сильно сужается, но нужно учитывать различия реализаций
- Низкая: по длине и внешнему виду нельзя утверждать однозначно
| Внешний признак | Первый кандидат | Уверенность | Примечание | Пример |
|---|---|---|---|---|
$argon2id$... |
Argon2id | Высокая | PHC string format. Часто дальше идут v=, m=, t=, p= |
$argon2id$v=19$m=65536,t=3,p=4$MDEyMzQ1Njc4OWFiY2RlZg$uKZLaN6muIyoyIYr5waqw3y+zaDbe9aLSPj6Ln/rbz4 |
$argon2i$... |
Argon2i | Высокая | То же | $argon2i$v=19$m=65536,t=3,p=4$MDEyMzQ1Njc4OWFiY2RlZg$Kx1koF/7n8EytGJYTS5krh+ag+FlG5ksM4xOsjOSDvo |
$argon2d$... |
Argon2d | Высокая | То же | $argon2d$v=19$m=65536,t=3,p=4$MDEyMzQ1Njc4OWFiY2RlZg$HLIGA+T1bwK8akx3LGOco+Df+PvxX6cIXhycO7O7t6c |
$2a$... / $2b$... / $2y$... |
bcrypt | Высокая | Двузначная стоимость + алфавит семейства crypt | $2b$12$9YQ2u/e5Y/ArOnG.gJKxK.0makLATcYLP1q.Nsabzrw7XErYCfoYO |
$1$... |
md5crypt | Высокая | Unix-формат хранения паролей на MD5 | $1$vA7mQ9xZ$Erz32JUFnZ9991KdU5.N3. |
$5$... |
sha256crypt | Высокая | Это не обычный SHA-256 | $5$rounds=5000$N3v8Kx2Lq9Rt$uOTla5GAHaRH2aHlUSjkrZUBCuFiahQZ36O/seB39r3 |
$6$... |
sha512crypt | Высокая | Это не обычный SHA-512 | $6$rounds=5000$N3v8Kx2Lq9Rt$6LUcSUAELX3aC/.60pTB.TFLTQi1mOGRCwKqNCqtRSaXjorxj01HJ9oNni97Kci1uDt7a/Kn4t3OS20Dw/.vi1 |
$7$... |
scrypt (семейство crypt) | Высокая | Встречается в реализациях семейства Linux crypt(5) |
$7$CU..../....k2XAnEHBqQ1Ct2aMXFKNa/$y3Q0e/UlCHacIGWQshgvvz6UIbP.BCja.5BfVWP2Ml8 |
$y$... |
yescrypt | Высокая | Встречается в более новых Linux-системах | $y$j9T$k2XAnEHBqQ1Ct2aMXFKNa/$OVYXzjlkiQpWT/F1CUE0JrvV4phLY8FB.ofDttnrSQ7 |
$apr1$... |
Apache APR1-MD5 | Высокая | Часто в .htpasswd |
$apr1$vA7mQ9xZ$ZE64.ohiyK11sPZmtnJZQ. |
{SHA}... |
Base64-представление digest SHA-1 | Высокая | Часто в Apache / LDAP | {SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE= |
{SSHA}... |
salted SHA-1 | Высокая | Семейство LDAP | {SSHA}/OczD0GNNkOAUPbYhA3L9fjmcyBCbHVlTWVzYTQyIQ== |
{MD5}... / {SMD5}... |
MD5 / salted MD5 | Высокая | Семейство LDAP | {MD5}X03MO1qnZdYdgyfeuILPmQ=={SMD5}fOn1rOv4ZH0OrO/KT9H0fEJsdWVNZXNhNDIh |
pbkdf2_sha256$... |
PBKDF2-HMAC-SHA256 | Средняя–высокая | Django и другие: реализация ставит имя формата в начало | pbkdf2_sha256$600000$N3v8Kx2Lq9Rt$CLxGB+zTiV1IdOt2y4m9JpaAONzHuRTOd96xKQwRQAs |
{bcrypt}$2b$... |
bcrypt | Высокая | С обёрткой {id} из Spring Security |
{bcrypt}$2b$12$9YQ2u/e5Y/ArOnG.gJKxK.0makLATcYLP1q.Nsabzrw7XErYCfoYO |
{pbkdf2}... / {scrypt}... |
Схема с меткой реализации | Средняя–высокая | Spring Security и подобные; важнее распознать формат обёртки, чем сам алгоритм | {pbkdf2}sha256$600000$Qmx1ZU1lc2E0MiE$4eNuai1qNkgs1kXz3+tBUMzAexVsSUz9SrQKEhbk0Cw{scrypt}ln=14,r=8,p=1$Qmx1ZU1lc2E0MiE$xAgBRhXbMtHB1UHUR0br5bI+1XdXWKbwauiFv5VRQBY |
Смысл таблицы: форматы, в которых первые несколько символов несут смысл, определяются надёжно.
Строки, разрезанные $...$, с высокой вероятностью относятся к Unix crypt(3) / MCF / PHC, и смотреть на prefix быстрее, чем на длину.
2.2 Таблица, которой сужают кандидатов по длине обычного hex / Base64
Эта таблица — для «голой» строки digest без префикса.
Если в записи смешаны :, - или пробелы, сначала уберите разделители и посчитайте длину.
| Длина в сырых байтах | Число hex-символов | Число символов Base64 (с = / без) |
Основные кандидаты | Пример |
|---|---|---|---|---|
| 4 | 8 | 8 / 6 | Контрольные суммы вроде CRC32 | cbf43926 |
| 16 | 32 | 24 / 22 | MD5, MD4, NT-хеш (на базе MD4) | 5f4dcc3b5aa765d61d8327deb882cf99 |
| 20 | 40 | 28 / 27 | SHA-1, RIPEMD-160 | da39a3ee5e6b4b0d3255bfef95601890afd80709 |
| 28 | 56 | 40 / 38 | SHA-224, SHA-512/224, SHA3-224 | d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f |
| 32 | 64 | 44 / 43 | SHA-256, SHA-512/256, SHA3-256, BLAKE2s-256, вывод BLAKE3 по умолчанию (32 байта) | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 |
| 48 | 96 | 64 / 64 | SHA-384, SHA3-384, BLAKE2b-384 | 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b |
| 64 | 128 | 88 / 86 | SHA-512, SHA3-512, BLAKE2b-512, Whirlpool | cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e |
Как читать столбец «Число символов Base64»: здесь рядом стоят два варианта — с padding = и без него. Base64 по RFC 4648 выравнивается по 4 символа, поэтому один или два = в конце появляются только тогда, когда длина в сырых байтах не кратна 3. В JWT и во встраивании в URL = часто отбрасывают, так что у одного и того же digest бывают и 43, и 44 символа. Наоборот, при 48 байтах (кратно 3) padding не возникает, поэтому в таблице стоит 64 / 64. Когда сужаете кандидатов по длине, сверяйтесь с обоими числами.
Главное: совпадение длины не делает схему однозначной. У шестнадцатеричных строк длиной 32 / 64 / 128 символов кандидатов особенно много; вывод только по длине легко промахивается.
2.3 Типичные примеры, в которых легко ошибиться
| Как выглядит строка | Типичный поспешный вывод | Как смотреть на самом деле | Пример |
|---|---|---|---|
5f4dcc3b5aa765d61d8327deb882cf99 |
Точно MD5 | Похоже на MD5, но возможны MD4, NT-хеш или прикладное использование MD5 | 8846f7eaee8fb117ad06bdd830b7586c |
64 hex, вроде 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 |
Точно SHA-256 | SHA-256 — кандидат, но возможны SHA3-256 / SHA-512/256 / BLAKE2s-256 / BLAKE3 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 |
$6$rounds=5000$salt$hash |
Hex-представление SHA-512 | Нет: это строка password hash sha512crypt | $6$rounds=5000$N3v8Kx2Lq9Rt$6LUcSUAELX3aC/.60pTB.TFLTQi1mOGRCwKqNCqtRSaXjorxj01HJ9oNni97Kci1uDt7a/Kn4t3OS20Dw/.vi1 |
{SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE= |
Какой-то «SHA» | В Apache / LDAP чаще всего digest SHA-1, закодированный в Base64 | {SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE= |
{bcrypt}$2b$12$... |
Некая собственная схема {bcrypt} |
bcrypt с обёрткой Spring Security | {bcrypt}$2b$12$9YQ2u/e5Y/ArOnG.gJKxK.0makLATcYLP1q.Nsabzrw7XErYCfoYO |
3. Практический порядок определения
Дальше — как смотреть по шагам. Рекомендуемый порядок: prefix → разделитель → набор символов → длина → контекст.
3.1 Сначала смотрим на первые символы
Уже по первым 1–10 символам круг сильно сужается.
-
$argon2id$/$argon2i$/$argon2d$Сильно подозреваем PHC string format Argon2. Составные части удобно смотреть в столбце «Пример» раздела 2.1. -
$2a$/$2b$/$2y$Сильно подозреваем bcrypt. -
$1$/$5$/$6$/$7$/$y$Подозреваем password hash семейства Unixcrypt(3). -
{SHA}/{SSHA}/{MD5}/{SMD5}Подозреваем представление семейства LDAP / Apache. -
{bcrypt}/{pbkdf2}/{scrypt}Подозреваем формат хранения с меткой реализации, как в Spring Security.
Приём здесь: смотреть не только на сам алгоритм, но и на формат хранения.
Например, $6$ — это не «digest SHA-512», а «строка password hash, которая использует SHA-512». Если их перепутать, дальше расследование поедет не туда.
3.2 Смотрим, сколько разделителей
Дальше смотрим на разделители вроде $, :, {}, ,, =.
-
Несколько
$Подозреваем формат, который вместе хранит параметры, salt и hash. Типичны Argon2, bcrypt, sha256crypt, sha512crypt. -
Начинается с
{name}Подозреваем обёртку с явно названной схемой, как в LDAP / Spring Security. -
Форма вроде
algo:salt:hashилиalgo$iterations$salt$hashПодозреваем формат фреймворка или приложения. Классика —pbkdf2_sha256$iterations$salt$hashв Django.
Чем больше разделителей, тем легче определить схему. Наоборот, один сплошной кусок hex или Base64 остаётся довольно неопределённым.
3.3 Смотрим на набор символов
Набор символов важен не меньше длины.
Шестнадцатеричное представление
Если строка состоит только из [0-9a-fA-F], сначала подозреваем hex.
Тогда число символов ÷ 2 = длина в сырых байтах.
- 32 hex → 16 байт
- 40 hex → 20 байт
- 64 hex → 32 байта
- 128 hex → 64 байта
Base64 / Base64url по RFC 4648
Есть + / = — сначала подозреваем обычный Base64.
Есть - _ — подозреваем Base64url.
Padding = иногда опускают, поэтому длина бывает «одной из двух», например 43 / 44, 86 / 88.
radix64 семейства crypt
Если встречаются . и /, да ещё разделитель $...$, естественнее подозревать не обычный Base64, а алфавит семейства crypt.
bcrypt, sha256crypt, sha512crypt, md5crypt, yescrypt, scrypt используют именно этот набор символов.
Момент неброский, но очень рабочий.
Решить, что «раз есть точка, это сломанный Base64», — лёгкий способ пропустить bcrypt и семейство crypt(3).
3.4 Считаем длину
После набора символов — длина. Логика простая.
- Для hex:
длина в сырых байтах = число символов / 2 - Для Base64:
число символов ≈ 4 × ceil(длина в сырых байтах / 3)Если padding=опущен, строка короче на 0–2 символа
На этом этапе круг кандидатов сужается. Но безопаснее не прыгать от «64 hex» сразу к «точно SHA-256».
3.5 Подтверждаем контекстом
В конце решает контекст. Здесь можно приблизиться к 100%.
-
Лежит в
/etc/shadowПодозреваем Linux-форматы password hash:$y$,$6$,$5$,$1$ -
Лежит в
.htpasswdПодозреваем семейство Apache:$apr1$,{SHA}, bcrypt -
Лежит в настройках Django или в
auth_user.passwordПодозреваем форматы Django:pbkdf2_sha256$...,argon2$... -
Лежит в таблице аутентификации Spring Security Подозреваем форматы с
{id}:{bcrypt}...,{pbkdf2}... -
32 hex рядом с интеграцией SMB / AD Сильно рассматриваем NT-хеш (на базе MD4)
На практике нередко быстрее посмотреть на продукт, фреймворк или имя файла конфигурации, откуда взялась строка, чем разбирать саму строку.
4. Частые ошибки определения
4.1 Жёстко решать «64 hex = SHA-256»
Так делают очень часто. SHA-256, конечно, сильный кандидат, но тот же 32-байтовый вывод дают несколько схем. SHA3-256, SHA-512/256, BLAKE2s-256, вывод BLAKE3 по умолчанию — той же длины.
Длина — материал для круга кандидатов, а не для окончательного вывода.
4.2 Принимать $6$ за обычный SHA-512
$6$... — префикс sha512crypt.
Это не «hex digest SHA-512», а строка password hash, в которой есть salt и rounds.
Аналогично:
$5$— sha256crypt$1$— md5crypt
Уже сам префикс означает, что перед вами не «просто digest».
4.3 Считать {SHA} «то ли SHA-256, то ли SHA-512»
В контексте Apache или LDAP {SHA} не означает расплывчато «что-то из семейства SHA».
В большинстве случаев это digest SHA-1, закодированный в Base64. {SSHA} — salted SHA-1.
Обращаться с {SHA} как с «каким-то SHA» по одному внешнему виду — способ ошибиться в коде проверки и в миграции.
4.4 Считать хеш пароля и хеш содержимого одним и тем же
Обе строки называют «хешем», но назначение разное.
- digest для проверки целостности файла
- digest для подписи API
- строка hash / KDF для хранения пароля
Внешне они похожи, обращаться с ними нужно по-разному. В частности, password hash часто включает в строку salt, rounds, memory cost, parallelism; подход «сравнить сырые digest» здесь не сработает.
4.5 Забывать про XOF и digest переменной длины
SHAKE128 / SHAKE256 — это XOF, длину вывода можно выбирать свободно. У BLAKE2 тоже можно менять длину digest, у BLAKE3 есть extendable output.
То есть вывод «такая длина, значит такая схема» промахивается, если слишком опирается на классический digest фиксированной длины.
4.6 Считать «NTLM» и «NT-хеш» одним и тем же
Это вопрос терминов, но в расследованиях вокруг Windows / AD он очень важен.
- NT-хеш: пароль кодируют в UTF-16LE и пропускают через MD4; получается 16-байтовое значение. На письме это 32 hex, например
8846f7eaee8fb117ad06bdd830b7586c. В спецификации этоNTOWFv1(Passwd, User, UserDom) = MD4(UNICODE(Passwd)). Определение дословно приведено в пункте NTLM v1 Authentication документа MS-NLMP — источник 13 в конце статьи. - NTLM: имя протокола аутентификации, который берёт это значение как ключ и делает challenge / response. Это не имя формата строки.
В разговоре «NTLM-хеш» тоже поймут, но в таблицу определения точнее писать NT-хеш (на базе MD4). Если разделить эти два смысла, не смешаются определение формата («эти 32 hex — MD5 или NT-хеш?») и разговор про протокол («этот обмен — NTLM или Kerberos?»).
У NT-хеша нет salt. Один и тот же пароль всегда даёт одни и те же 32 hex, поэтому сама картина «в таблице из AD лежат 32 hex без salt» уже подсказка.
5. Порядок проверки, если нужна стопроцентная уверенность
При миграции или стыковке аутентификации в конце концов нужна определённость. Тогда смотреть в таком порядке — меньше шансов ошибиться.
5.1 Определить источник хранения
Сначала устанавливаем, откуда строка.
- Linux shadow?
- basic auth Apache / Nginx?
- LDAP?
- Django / Spring Security?
- БД собственного приложения?
Часто спецификация источника сильнее, чем сама строка.
5.2 Искать в официальной документации именно «формат хранения»
Дальше ищем не имя алгоритма, а формат хранения.
Django password formatSpring Security password storage formatcrypt(5) sha512crypt formatApache htpasswd password formats
Искать по словам format / storage / encoding обычно быстрее.
5.3 Если есть известный открытый текст — сверить с кандидатами напрямую
Есть тестовая учётная запись или известный открытый текст — быстрее всего посчитать значение по каждой кандидатной схеме и сравнить. Для password hash при этом нужно достать salt и rounds из строки и пересчитать.
Шаблон один и тот же, три шага для любой схемы.
- Достать salt и параметры из строки
- Пересчитать известный открытый текст с теми же salt и параметрами
- Посмотреть, полностью ли совпадает получившаяся строка с исходной
Проверяем digest без префикса
Сначала «просто digest». Хватает стандартной библиотеки Python 3.
# Python 3.8+ / только стандартная библиотека
import base64
import hashlib
target = "5f4dcc3b5aa765d61d8327deb882cf99" # строка, которую определяем
plain = b"password" # известный открытый текст
for name in ("md5", "sha1", "sha256", "sha512", "sha3_256", "blake2s"):
digest = hashlib.new(name, plain).digest()
if digest.hex() == target.lower():
print("совпало hex:", name)
if base64.b64encode(digest).decode() == target:
print("совпало base64:", name)
В этом примере печатается совпало hex: md5. Базовая форма — поставить в for те схемы, которые вынесли в кандидаты в таблице 2.2.
Если захотите проверить NT-хеш, пишут что-то вроде hashlib.new("md4", "password".encode("utf-16-le")), но в Python, собранном с OpenSSL 3, legacy provider по умолчанию выключен, поэтому бывает unsupported hash type md4. Это лучше заранее проверить на своей машине.
Проверяем password hash семейства crypt
$1$ / $5$ / $6$ / $apr1$ можно пересчитать, передав salt в openssl passwd. Примеры из таблицы 2.1 воспроизводятся именно так.
# OpenSSL 3.x
openssl passwd -6 -salt N3v8Kx2Lq9Rt password
# $6$N3v8Kx2Lq9Rt$6LUcSUAELX3aC/.60pTB.TFLTQi1mOGRCwKqNCqtRSaXjorxj01HJ9oNni97Kci1uDt7a/Kn4t3OS20Dw/.vi1
openssl passwd -5 -salt N3v8Kx2Lq9Rt password # sha256crypt
openssl passwd -1 -salt vA7mQ9xZ password # md5crypt
openssl passwd -apr1 -salt vA7mQ9xZ password # Apache APR1-MD5
Если вывод совпал с проверяемой строкой, в этот момент подтверждаются и схема, и открытый текст.
Если в строке есть rounds=, это значение тоже нужно передать. $6$rounds=5000$... — значение по умолчанию, поэтому с явным указанием и без него digest один и тот же; если же стоит, например, rounds=100000 и это не значение по умолчанию, считать нужно обязательно с ним.
На Debian / Ubuntu то же самое умеет mkpasswd из пакета whois (вид mkpasswd -m sha512crypt -S N3v8Kx2Lq9Rt password).
Проверяем bcrypt и Argon2
У bcrypt и Argon2 salt закодирован собственным алфавитом, поэтому надёжнее не вырезать его вручную, а отдать строку целиком в verify библиотеки.
# pip install "passlib[bcrypt]" argon2-cffi
from passlib.hash import argon2, bcrypt
samples = [
(bcrypt, "$2b$12$9YQ2u/e5Y/ArOnG.gJKxK.0makLATcYLP1q.Nsabzrw7XErYCfoYO"),
(argon2, "$argon2id$v=19$m=65536,t=3,p=4$MDEyMzQ1Njc4OWFiY2RlZg$uKZLaN6muIyoyIYr5waqw3y+zaDbe9aLSPj6Ln/rbz4"),
]
for handler, stored in samples:
# identify — тот ли это формат; verify — совпадает ли открытый текст
print(handler.name, handler.identify(stored), handler.verify("password", stored))
verify сам читает cost, rounds и salt из строки и пересчитывает, поэтому доставать параметры вручную не нужно. В примере bcrypt открытый текст — password, поэтому вернётся True.
Модуль crypt из стандартной библиотеки Python объявлен нерекомендуемым и удалён в Python 3.13. Если на 3.13 и новее нужно работать с семейством crypt, опирайтесь на openssl passwd или на passlib.
5.4 Перевести кандидатную схему в номер hashcat или имя john
Когда открытый текст неизвестен и хочется работать инструментом, имя схемы нужно перевести в идентификатор инструмента. Здесь часто застревают, поэтому типичные соответствия сведены в таблицу.
| Внешний вид | Схема | Режим hashcat (-m) |
|---|---|---|
| 32 hex | MD5 | 0 |
| 32 hex (из AD) | NT-хеш | 1000 |
| 40 hex | SHA-1 | 100 |
| 64 hex | SHA-256 | 1400 |
| 128 hex | SHA-512 | 1700 |
$1$... |
md5crypt | 500 |
$apr1$... |
Apache APR1-MD5 | 1600 |
$2a$ / $2b$ / $2y$ |
bcrypt | 3200 |
$5$... |
sha256crypt | 7400 |
$6$... |
sha512crypt | 1800 |
pbkdf2_sha256$... |
Django PBKDF2-HMAC-SHA256 | 10000 |
| формат хранения семейства scrypt | scrypt | 8900 |
Номера режимов растут от версии к версии, поэтому для более новых схем вроде Argon2 или yescrypt сверяйтесь со списком в справке той hashcat, которая стоит у вас.
John the Ripper задаёт схему не числом, а именем. В базовой сборке (1.8.0) доступны descrypt, bsdicrypt, md5crypt, bcrypt, LM, AFS, tripcode, dummy, crypt; большая часть остальных добавляется в jumbo. Если нужного имени нет в базовой сборке, смотрите документацию jumbo.
Ещё раз: эти инструменты используйте только против своей среды или среды, где расследование разрешено.
5.5 Проверить код реализации или конфигурацию
Если исследуемая система своя, в конце надёжнее всего посмотреть код и конфигурацию.
- используемая библиотека
- настройки фреймворка
- опции на этапе генерации
- способ кодирования вывода (hex / Base64 / Base64url / алфавит crypt)
Обычно на этом вопрос закрывается.
5.6 На будущее — хранить с меткой схемы
Если систему проектируете вы, формат, который встраивает имя схемы в строку, сильно облегчит будущую миграцию.
- PHC string format Argon2
{id}encodedPasswordв Spring Securityalgo$iterations$salt$hashв Django- форматы семейства Unix
crypt(3)с префиксом
Тогда тому, кто будет смотреть позже, проще не заблудиться. Наоборот, класть в БД «просто 64 hex» к будущему себе недоброжелательно.
6. Итог
Когда по строковому представлению хеша нужно отличить схему, удобно смотреть в таком порядке.
- Есть ли prefix
- Какие разделители
- Какой набор символов
- Скольким байтам соответствует длина
- Каков контекст источника хранения
Важнее всего два пункта.
- Форматы хранения с префиксом определяются довольно точно
- Обычный hex / Base64 чаще дают только круг кандидатов
Поэтому на практике решение такое.
- Для
$argon2id$...,$2b$...,$6$...,{SHA}...,pbkdf2_sha256$...одной строки уже достаточно, чтобы сильно продвинуться - Для просто 32 / 40 / 64 / 128 hex думаем «сужаем кандидатов», а не «выносим вердикт»
- Если действительно нужна определённость, смотрим продукт-источник, конфигурацию и реализацию
Такой порядок заметно ускоряет расследование. Поспешный вывод только по длине, наоборот, тихо уводит в сторону.
7. Услуги, связанные с этой темой
Техническая консультация и ревью архитектуры
Определить схему хеша пароля, оставшегося в существующей БД, спланировать миграцию платформы аутентификации, разобрать логи смешанной системы Windows / Web — для этого нужно упорядочить не только внешний вид строки, но и реализацию источника, и политику миграции. Если смотреть целиком, от определения схемы до проектирования миграции, ошибок обычно меньше.
Расследование сбоев и анализ причин
Нередки расследования, которые упираются в «непонятно, что это за строка, и проверка не движется». Если отделить, где именно задаётся схема — в логах, файлах конфигурации, схеме БД или в коде приложения, — причина находится заметно быстрее.
8. Источники
- RFC 1321 - The MD5 Message-Digest Algorithm
- NIST FIPS 180-4 - Secure Hash Standard (SHA-1, SHA-2, SHA-512/224, SHA-512/256)
- NIST FIPS 202 - SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions
- PHC string format specification
- Argon2 reference implementation
- RFC 7693 - The BLAKE2 Cryptographic Hash and Message Authentication Code (MAC)
- BLAKE3 C README - default output length and extendable output
- crypt(5) - prefixes and hashed passphrase formats
- Apache HTTP Server 2.4 - Password Formats
- slappasswd(8) - RFC 2307 schemes such as {SHA} and {SSHA}
- Django documentation - example of
pbkdf2_sha256$... - Spring Security -
DelegatingPasswordEncoderstorage format{id}encodedPassword - MS-NLMP: NTLM v1 Authentication -
NTOWFv1(Passwd, User, UserDom) = MD4(UNICODE(Passwd)) - hashcat wiki - example hashes(список режимов)
- John the Ripper - command line options(имена для
--format=NAME) - passlib -
PasswordHashAPI(identifyиverify) - openssl-passwd(1) -
-1/-apr1/-5/-6и-salt
Похожие статьи
Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.
Ускоряет ли Windows отключение целостности памяти (HVCI) — что это значит, как делать и как решать
Действительно ли отключение целостности памяти (HVCI) ускоряет ПК с Windows? Когда помогает, когда нет, как выключить и вернуть и как при...
Глубины виртуализации Windows (часть 2) — память, которую не видит даже ядро: как устроены VBS, HVCI и Credential Guard
На совместимом оборудовании при чистой установке VBS включена по умолчанию: гипервизор и SLAT создают изоляцию сильнее ядра. Разбираем ус...
Именованные каналы на практике — от проектирования до безопасности IPC в Windows
Практический разбор именованных каналов — стандартного IPC в Windows. По первоисточникам: выбор байтового режима и режима сообщений, серв...
Учётные записи служб Windows: LocalSystem, виртуальные учётные записи и gMSA
Службы Windows всё ещё запускают от LocalSystem? Статья сравнивает права и то, кем служба выглядит в сети, у LocalService, NetworkService...
Политика аудита безопасности Windows и расследование журнала событий на практике — как стать ИТ-службой, которая умеет читать 4625
Практическое руководство, чтобы ответить на просьбу «посмотрите журналы неудачных входов». Разбирает связь базовой и расширенной политики...
Связанные темы
Эти страницы показывают тему статьи в более широком контексте услуг и решений.
Технические темы Windows
Раздел о разработке Windows, расследовании сбоев и использовании существующих активов.
Услуги по этой теме
Статья напрямую связана со следующими услугами.
Технические консультации и ревью дизайна
Подходит для задач, где нужно разделить логи, БД, метод аутентификации и формат хранения существующей системы, определить схему хеша и упорядочить решения по миграции или расследованию.
Частые вопросы
Вопросы, которые часто возникают при консультациях по теме статьи.
- В каком порядке смотреть, чтобы отличить схему по строке хеша?
- Удобнее идти в порядке prefix → разделитель → набор символов → длина → контекст. Форматы, в которых первые несколько символов несут смысл, определяются легко: $argon2id$ — сильно подозреваем Argon2, $2b$ — bcrypt, $5$ — sha256crypt, $6$ — sha512crypt. Наоборот, обычный hex или Base64 без префикса позволяют лишь сузить круг кандидатов, поэтому окончательно схему подтверждают по продукту-источнику, фреймворку и конфигурации.
- Можно ли утверждать, что 64-символьная шестнадцатеричная строка — это SHA-256?
- Утверждать опасно. SHA-256 — сильный кандидат, но тот же 32-байтовый вывод дают SHA3-256, SHA-512/256, BLAKE2s-256, вывод BLAKE3 по умолчанию и другие схемы; по одной длине их не различить. Длина — материал для круга кандидатов, а не для окончательного вывода. Если нужна определённость, придётся дойти до спецификации источника, формата хранения в официальной документации, сверки с известным открытым текстом и проверки кода реализации или конфигурации.
- Строка, которая начинается с $6$, — это хеш SHA-512?
- Нет. $6$ — префикс Unix-формата хранения паролей sha512crypt. Это не hex digest SHA-512 как таковой, а строка хеша пароля, в которой есть salt и rounds. Аналогично $5$ — sha256crypt, $1$ — md5crypt. Уже сам префикс означает, что перед вами не «просто digest»; если их перепутать, разъедутся миграция и код проверки.
- Что можно понять по набору символов в строке?
- Набор символов — такая же важная подсказка, как длина. Если встречаются только символы 0-9a-fA-F, это шестнадцатеричное представление, и половина числа символов — длина в сырых байтах. + / = говорят о Base64 по RFC 4648, - и _ — о Base64url. Если есть точка и слэш, а разделитель — $, естественнее подозревать не обычный Base64, а алфавит семейства crypt, как у bcrypt или sha512crypt. Принять строку с точкой за «сломанный» Base64 — значит пропустить форматы crypt.
Об авторе
Страница с профилем автора статьи.
Го Комура
Представитель KomuraSoft LLC
Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.