crypt — это функция библиотеки POSIX C. Обычно она используется для вычисления хеша паролей учетных записей пользователей. Функция выводит текстовую строку, которая также кодирует соль (обычно первые два символа — это сама соль, а остальные — хешированный результат), и идентифицирует используемый алгоритм хеширования (по умолчанию «традиционный», описанный ниже). Эта выходная строка формирует запись пароля, которая обычно хранится в текстовом файле.
Более формально, crypt предоставляет функции создания криптографических ключей для проверки и хранения паролей в системах Unix.
В Unix есть не связанная утилита crypt , которую часто путают с функцией библиотеки C. Чтобы различать эти два понятия, авторы часто называют утилиту crypt(1) , поскольку она документирована в разделе 1 страниц руководства Unix , а функцию библиотеки C называют crypt(3) , поскольку ее документация находится в разделе 3 руководства. [1]
Эта же функция шифрования используется как для генерации нового хеша для хранения, так и для хеширования предложенного пароля с записанной солью для сравнения.
Современные реализации Unix библиотеки криптографии поддерживают множество схем хэширования. Конкретный используемый алгоритм хэширования может быть идентифицирован по уникальному префиксу кода в результирующем хэш-тексте, следуя фактическому стандарту, называемому Modular Crypt Format. [2] [3] [4]
Функция crypt()
библиотеки также включена в языки программирования Perl , [5] PHP , [6] Pike , [7] Python [8] (хотя она теперь устарела с версии 3.11) и Ruby [9] .
Со временем были введены различные алгоритмы. Для обеспечения обратной совместимости каждая схема начала использовать некоторое соглашение о сериализации хэшей паролей , которое позже было названо Modular Crypt Format (MCF). [3] Старые хэши crypt(3), созданные до фактического стандарта MCF, могут различаться от схемы к схеме. Четко определенное подмножество Modular Crypt Format было создано во время соревнования Password Hashing Competition . [3] Формат определяется как: [10]
$<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]]
где
id
: идентификатор, представляющий алгоритм хеширования (например, 1 для MD5 , 5 для SHA-256 и т. д.)param
имя и его value
параметры сложности хэша, такие как количество раундов/итерацийsalt
: соль , следующая за алфавитом radix-64 (DES использует декодированное значение)hash
: закодированный в radix-64 результат хеширования пароля и солиКодировка radix-64 в crypt называется B64 и использует алфавит ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
, который отличается от более распространенного RFC 4648 base64.
Подмножество PHC охватывает большинство хэшей MCF. Существует ряд дополнительных методов, определяемых приложением. [3]
Первоначальная реализация библиотечной функции crypt() [11] в третьем издании Unix [12] имитировала шифровальную машину M-209 . Вместо того, чтобы шифровать пароль ключом, что позволило бы восстановить пароль из зашифрованного значения и ключа, она использовала сам пароль в качестве ключа, а база данных паролей содержала результат шифрования пароля этим ключом.
Первоначальная схема шифрования паролей оказалась слишком быстрой и, таким образом, подверженной перебору наиболее вероятных паролей. [11] В седьмом издании Unix [ 13] схема была изменена на модифицированную форму алгоритма DES . Целью этого изменения было сделать шифрование медленнее. Кроме того, алгоритм включал 12-битную соль , чтобы гарантировать, что злоумышленник будет вынужден взламывать каждый пароль независимо, а не иметь возможность атаковать всю базу паролей одновременно.
Подробно, пароль пользователя усекается до восьми символов, и они приводятся к 7 битам каждый; это формирует 56-битный ключ DES. Затем этот ключ используется для шифрования блока из всех битов-нулей, а затем шифротекст снова шифруется тем же ключом, и так далее, в общей сложности 25 шифрований DES. 12-битная соль используется для возмущения алгоритма шифрования, поэтому стандартные реализации DES не могут использоваться для реализации crypt(). Соль и окончательный шифротекст кодируются в печатную строку в форме base64 .
Технически это не шифрование, поскольку данные (все биты нулевые) не хранятся в секрете; они широко известны всем заранее. Однако одно из свойств DES заключается в том, что он очень устойчив к восстановлению ключа даже в ситуациях с известным открытым текстом . Теоретически возможно, что два разных пароля могут привести к абсолютно одинаковому хешу. Таким образом, пароль никогда не «расшифровывается»: он просто используется для вычисления результата, и совпадающие результаты считаются доказательством того, что пароли были «одинаковыми».
Преимущества этого метода заключаются в том, что хэш-текст можно хранить и копировать между системами Unix, не раскрывая соответствующий открытый текстовый пароль системным администраторам или другим пользователям. Эта переносимость работает уже более 30 лет во многих поколениях вычислительной архитектуры и во многих версиях Unix от многих поставщиков.
Первоначально был выбран традиционный алгоритм шифрования на основе DES, поскольку DES был устойчив к восстановлению ключа даже при атаках с использованием «известного открытого текста», а также потому, что он был затратным в вычислительном отношении. На самых ранних машинах Unix для вычисления хеша пароля требовалось более целой секунды. Это также делало его достаточно устойчивым к атакам по словарю в ту эпоху. В то время хеши паролей обычно хранились в файле учетной записи ( /etc/passwd
), который мог прочитать любой пользователь системы. (Этот файл учетной записи также использовался для преобразования номеров идентификаторов пользователей в имена, а имен пользователей в полные имена и т. д.).
За три десятилетия с тех пор компьютеры стали намного мощнее. Закон Мура в целом соблюдался, поэтому скорость и мощность компьютера, доступные для заданных финансовых инвестиций, удвоились более чем в 20 раз с момента написания Unix. Это давно сделало алгоритм на основе DES уязвимым для атак по словарю, а Unix и Unix-подобные системы, такие как Linux, долгое время использовали «теневые» файлы , перенося только значения хэша пароля из файла учетной записи ( /etc/passwd
) в файл (условно называемый /etc/shadow
), который могут читать только привилегированные процессы.
Чтобы увеличить вычислительную стоимость взлома пароля, некоторые сайты Unix в частном порядке начали увеличивать количество раундов шифрования на ad hoc основе. [ требуется цитата ] Это имело побочный эффект, сделав их crypt()
несовместимыми со стандартом crypt()
: хеши имели ту же текстовую форму, но теперь вычислялись с использованием другого алгоритма. Некоторые сайты также воспользовались этим эффектом несовместимости, изменив начальный блок со стандартного all-bits-zero. [ необходима цитата ] Это не увеличило стоимость хеширования, но означало, что предварительно вычисленные хеш-словари на основе стандартного crypt() не могли быть применены.
BSDi использовала небольшую модификацию классической схемы на основе DES. BSDi расширила соль до 24 бит и сделала количество раундов переменным (до 2 24 -1). Выбранное количество раундов кодируется в сохраненном хэше пароля, избегая несовместимости, которая возникала, когда сайты изменяли количество раундов, используемых в исходной схеме. Эти хэши идентифицируются по начинающимся с подчеркивания ( _
), за которым следуют 4 символа, представляющие количество раундов, а затем 4 символа для соли.
Алгоритм BSDi также поддерживает более длинные пароли, используя DES для сжатия исходного длинного пароля до восьми 7-битных байтов, поддерживаемых исходным алгоритмом.
Poul-Henning Kamp разработал причудливый и (в то время) вычислительно затратный алгоритм, основанный на алгоритме дайджеста сообщений MD5 . Сам по себе MD5 обеспечивает хорошую криптографическую стойкость для хэша пароля, но он разработан так, чтобы его можно было вычислить довольно быстро относительно стойкости, которую он обеспечивает. Схема crypt() разработана так, чтобы его было трудно вычислить, чтобы замедлить атаки по словарю. Печатная форма хэшей паролей MD5 начинается с $1$
.
Эта схема позволяет пользователям иметь пароль любой длины, и они могут использовать любые символы, поддерживаемые их платформой (не только 7-битный ASCII). (На практике многие реализации ограничивают длину пароля, но, как правило, поддерживают пароли гораздо большей длины, чем любой человек готов ввести.) Соль также является произвольной строкой, ограниченной только соображениями набора символов.
Сначала парольная фраза и соль хэшируются вместе, давая дайджест сообщения MD5. Затем создается новый дайджест, хэширующий вместе парольную фразу, соль и первый дайджест, все в довольно сложной форме. Затем этот дайджест проходит через тысячу итераций функции, которая повторно хэширует его вместе с парольной фразой и солью способом, который меняется между раундами. Выход последнего из этих раундов — это результирующий хэш парольной фразы.
Фиксированное количество итераций привело к тому, что эта схема потеряла вычислительные затраты, которые она когда-то имела, и теперь предпочтение отдается переменному количеству раундов. В июне 2012 года Пол-Хеннинг Камп объявил алгоритм небезопасным и призвал пользователей перейти на более сильные шифраторы паролей. [14]
Нильс Провос и Дэвид Мазьер разработали схему crypt() под названием bcrypt на основе Blowfish и представили ее на USENIX в 1999 году. [15] Печатная форма этих хэшей начинается с $2$
, $2a$
, $2b$
, $2x$
или $2y$
в зависимости от того, какой вариант алгоритма используется:
$2$
- Устаревший.$2a$
– Текущий ключ, используемый для идентификации этой схемы. Поскольку в 2011 году в реализации алгоритма crypt_blowfish, отличной от OpenBSD, была обнаружена серьезная уязвимость безопасности, [16] хэши, указанные этой строкой, теперь неоднозначны и могли быть сгенерированы неисправной реализацией или последующей исправленной реализацией. Уязвимость может быть вызвана некоторыми строками паролей, содержащими символы, не относящиеся к ASCII (8-битовый набор).$2b$
– Используется в последних реализациях OpenBSD для включения смягчения проблемы зацикливания. [17] Предыдущие версии алгоритма имели проблему с длинными паролями. По замыслу длинные пароли усекаются до 72 символов, но существует проблема зацикливания байтового целого числа с определенными длинами паролей, что приводит к слабым хэшам. [18]$2x$
– Флаг, добавленный после обнаружения ошибки crypt_blowfish . Старые хэши можно переименовать в be, чтобы указать, что они были сгенерированы с помощью сломанного алгоритма. Эти хэши все еще слабы, но, по крайней мере, ясно, какой алгоритм использовался для их генерации.$2x$
$2y$
– Флаг в crypt_blowfish для однозначного использования нового, исправленного алгоритма. На старой реализации, страдающей от ошибки, просто не будет работать. На новой, исправленной реализации это даст тот же результат, что и использование .$2y$
$2b$
Blowfish выделяется среди блочных шифров своей дорогой фазой настройки ключа. Он начинается с подключей в стандартном состоянии, затем использует это состояние для выполнения блочного шифрования с использованием части ключа и использует результат этого шифрования (на самом деле хеширования) для замены некоторых подключей. Затем он использует это измененное состояние для шифрования другой части ключа и использует результат для замены большего количества подключей. Он продолжает таким образом, используя постепенно измененное состояние для хеширования ключа и замены битов состояния, пока все подключи не будут установлены.
Число раундов ключа — это степень двойки, которая является входными данными для алгоритма. Число кодируется в текстовом хэше, например$2y$10...
FreeBSD реализовала поддержку алгоритма хэширования NT LAN Manager для обеспечения более простой совместимости с учетными записями NT через MS-CHAP . [19] Известно, что алгоритм NT-Hash слаб, поскольку он использует устаревший алгоритм хэширования md4 без какой-либо соли. [20] FreeBSD использовала $3$
для этого префикс. Его использование не рекомендуется, так как его легко взломать. [1]
Широко используемая схема на основе MD5 стала более доступной для атак по мере увеличения мощности компьютеров. Хотя система на основе Blowfish имеет возможность добавлять раунды и, таким образом, остается сложным алгоритмом пароля, она не использует алгоритм, одобренный NIST . В свете этих фактов Ульрих Дреппер Red Hat возглавил попытку создать схему на основе хэш-функций SHA-2 (SHA-256 и SHA-512). [21] Печатная форма этих хэшей начинается с $5$
(для SHA-256) или $6$
(для SHA-512) в зависимости от того, какой вариант SHA используется. Его конструкция похожа на криптографию на основе MD5, с несколькими заметными отличиями: [21]
Спецификация и пример кода были опубликованы в открытом доступе; их часто называют «SHAcrypt». [24]
$y$
$7$
) и финалист PHC. Он используется в нескольких дистрибутивах Linux как альтернатива существующим схемам. [25] Для использования этого хэша хэш libcrypt
из glibc заменяется обратно совместимым хэшем из проекта "libxcrypt". [26]$argon2d$
, $argon2i$
,$argon2ds$
Дополнительные форматы, если таковые имеются, описаны на страницах руководства по реализациям. [27]
BigCrypt — это модифицированная версия DES-Crypt, используемая в HP-UX, Digital Unix и OSF/1. Главное отличие от DES заключается в том, что BigCrypt использует все символы пароля, а не только первые 8, и имеет хэш переменной длины. [28]
Crypt16 — это небольшая модификация DES, которая позволяет использовать пароли длиной до 16 символов. Используется в Ultrix и Tru64. [29]
Библиотека GNU C (glibc), используемая почти всеми дистрибутивами Linux, обеспечивает реализацию функции crypt , которая поддерживает алгоритмы хеширования на основе DES, MD5 и (начиная с версии 2.7) SHA-2, упомянутые выше. Ульрих Дреппер, сопровождающий glibc, отклонил поддержку bcrypt (схема 2), поскольку она не одобрена NIST . [32] Для систем без bcrypt доступна общедоступная библиотека crypt_blowfish . Она была интегрирована в glibc в SUSE Linux . [33]
В августе 2017 года glibc объявила о планах полностью удалить свою реализацию crypt. В ответ на это ряд дистрибутивов Linux (включая Fedora и Debian, но не ограничиваясь ими) перешли на libxcrypt — реализацию, совместимую с ABI, которая дополнительно поддерживает новые алгоритмы, включая bcrypt и yescrypt. [34]
Библиотека musl C поддерживает схемы 1, 2, 5 и 6, а также традиционную схему DES. Традиционный код DES основан на BSD FreeSec с модификацией для совместимости с glibc UFC-Crypt . [35]
Собственный Darwin crypt()
обеспечивает ограниченную функциональность, поддерживая только DES и BSDi. OS X использует несколько систем для собственных хэшей паролей, начиная от старой NeXTStep netinfo и заканчивая новой системой служб каталогов (ds). [36] [37]