crypt — это библиотечная функция POSIX C. Обычно он используется для вычисления хеша паролей учетных записей пользователей. Функция выводит текстовую строку, которая также кодирует соль (обычно первые два символа — это сама соль, а остальные — хешированный результат) и идентифицирует используемый алгоритм хеширования (по умолчанию используется «традиционный», описанный ниже) . Эта выходная строка формирует запись пароля, которая обычно хранится в текстовом файле.
Более формально, crypt предоставляет функции получения криптографических ключей для проверки и хранения паролей в системах Unix.
В Unix есть несвязанная утилита шифрования , которую часто путают с функцией библиотеки C. Чтобы различать эти два понятия, авторы часто называют служебную программу crypt(1) , поскольку она описана в разделе 1 страниц руководства Unix , а функцию библиотеки C называют crypt(3) , поскольку ее документация находится в раздел руководства 3. [1]
Эта же функция шифрования используется как для генерации нового хеша для хранения, так и для хеширования предложенного пароля с записанной солью для сравнения.
Современные реализации библиотеки crypt в Unix поддерживают множество хеш-схем. Конкретный используемый алгоритм хэширования можно идентифицировать по уникальному префиксу кода в результирующем хэш-тексте, соответствующем стандарту де-факто, называемому модульным форматом шифрования. [2] [3] [4]
Библиотечная crypt()
функция также включена в языки программирования Perl , [5] PHP , [6] Pike , [7] Python [8] (хотя с версии 3.11 она устарела) и Ruby [9] .
Со временем были введены различные алгоритмы. Чтобы обеспечить обратную совместимость , каждая схема начала использовать некоторое соглашение о сериализации хэшей паролей , которое позже было названо Modular Crypt Format (MCF). [3] Старые хеши crypt(3), созданные до фактического стандарта MCF, могут варьироваться от схемы к схеме. Четко определенное подмножество формата модульного шифрования было создано во время конкурса хеширования паролей . [3] Формат определяется как: [10]
$<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]]
где
id
: идентификатор, представляющий алгоритм хеширования (например, 1 для MD5 , 5 для SHA-256 и т. д.) .param
имя и его value
параметры сложности хэша, такие как количество раундов/итераций.salt
: соль , следующая за алфавитом счисления 64 (DES использует декодированное значение)hash
: результат хеширования пароля и соли в кодировке radix-64Кодировка по основанию 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 в частном порядке начали увеличивать количество раундов шифрования на разовой основе. [ нужна цитата ] Побочным эффектом этого стало то, что они стали crypt()
несовместимы со стандартом crypt()
: хэши имели ту же текстовую форму, но теперь вычислялись с использованием другого алгоритма. Некоторые сайты также воспользовались этим эффектом несовместимости, изменив исходный блок со стандартного «все биты — ноль». [ нужна цитата ] Это не увеличивало стоимость хеширования, но означало, что предварительно вычисленные хэш-словари, основанные на стандартном crypt() , не могли быть применены.
BSDi использовала небольшую модификацию классической схемы на основе DES. BSDi расширил соль до 24 бит и сделал число раундов переменным (до 2 24 -1). Выбранное количество раундов кодируется в сохраненном хеше пароля, что позволяет избежать несовместимости, которая возникала, когда сайты изменяли количество раундов, используемое исходной схемой. Эти хэши идентифицируются, начиная с символа подчеркивания ( _
), за которым следуют 4 символа, представляющие количество раундов, а затем 4 символа для соли.
Алгоритм BSDi также поддерживает более длинные пароли, используя DES для сжатия исходного длинного пароля до восьми 7-битных байтов, поддерживаемых исходным алгоритмом.
Пол-Хеннинг Камп разработал причудливый и (на тот момент) дорогостоящий в вычислительном отношении алгоритм, основанный на алгоритме дайджеста сообщения 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 . Старые хэши можно переименовать, чтобы указать, что они были созданы с использованием сломанного алгоритма. Эти хеши пока еще слабые, но, по крайней мере, ясно, какой алгоритм использовался для их генерации.$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
from 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 , используемая почти во всех дистрибутивах Linux, обеспечивает реализацию функции crypt , которая поддерживает упомянутые выше алгоритмы хеширования на основе DES, MD5 и (начиная с версии 2.7) SHA-2. Ульрих Дреппер, сопровождающий glibc, отклонил поддержку bcrypt (схема 2), поскольку она не одобрена NIST . [31] Для систем без bcrypt доступна общедоступная библиотека crypt_blowfish . Он был интегрирован в glibc в SUSE Linux . [32] Кроме того, вышеупомянутая libxcrypt используется для замены glibc crypt() в системах с поддержкой Yescrypt.
Библиотека musl C поддерживает схемы 1, 2, 5 и 6, а также традиционную схему DES. Традиционный код DES основан на BSD FreeSec с модификациями для совместимости с glibc UFC-Crypt . [33]
Родной вариант Darwin crypt()
предоставляет ограниченную функциональность, поддерживая только DES и BSDi. OS X использует несколько систем для своих собственных хэшей паролей, начиная от старой NeXTStep netinfo и заканчивая новой системой служб каталогов (ds). [34] [35]