bcrypt - bcrypt

редактировать
bcrypt
Общие
ДизайнерыНильс Провос, Дэвид Мазьер
Впервые опубликовано1999
Получено изBlowfish (шифр)
Подробности
Размеры дайджеста 184 бит
Округляетпеременную с помощью параметра стоимости

bcrypt - это функция хеширования паролей, разработанная Нильсом Провосом и Дэвидом Мазьером на основе шифра Blowfish и представленная на USENIX в 1999 г.. Помимо включения соли для защиты от атак радужной таблицы, bcrypt является адаптивной функцией: с течением времени количество итераций может быть увеличено, чтобы сделать его медленнее, поэтому он остается устойчивым к поиск грубой силы атакует даже при увеличении вычислительной мощности.

Функция bcrypt - это пароль по умолчанию хэш-алгоритм для OpenBSD и других систем, включая некоторые дистрибутивы Linux, такие как SUSE Linux.

Существуют реализации bcrypt для C, C ++, C#, Elixir,Go,Java, JavaScript, Perl, PHP, Python, Ruby и другие языки.

Содержание
  • 1 Предпосылки
  • 2 Описание
  • 3 История версий
  • 4 Алгоритм
    • 4.1 Дорогостоящая настройка ключа
    • 4.2 Расширение ключа
  • 5 Пользовательский ввод
  • 6 Критические замечания
    • 6.1 Максимальная длина пароля
    • 6.2 Усечение хэша пароля
    • 6.3 Использование нестандартной кодировки base64
  • 7 См. Также
  • 8 Ссылки
  • 9 Внешние ссылки
Справочная информация

Blowfish выделяется среди блочных шифров своей дорогой фазой настройки ключа. Он начинается с подключей в стандартном состоянии, затем использует это состояние для выполнения блочного шифрования с использованием части ключа и использует результат этого шифрования (который более точен при хешировании) для замены некоторых подключей. Затем он использует это измененное состояние для шифрования другой части ключа и использует результат для замены большего количества подключей. Он действует таким образом, используя прогрессивно измененное состояние для хеширования ключа и замены битов состояния, пока не будут установлены все подключи.

Прово и Мазьер воспользовались этим и пошли дальше. Они разработали новый алгоритм настройки ключей для Blowfish, назвав получившийся шифр «Eksblowfish» («дорогостоящее расписание ключей для Blowfish»). Настройка ключа начинается с измененной формы стандартной настройки ключа Blowfish, в которой и соль, и пароль используются для установки всех подключей. Затем существует ряд раундов, в которых применяется стандартный алгоритм набора ключей Blowfish с альтернативным использованием соли и пароля в качестве ключа, причем каждый раунд начинается с состояния подключей из предыдущего раунда. Теоретически это не сильнее стандартного расписания ключей Blowfish, но количество раундов смены ключей можно настроить; поэтому этот процесс можно сделать сколь угодно медленным, что помогает предотвратить атаки методом перебора хэша или соли.

Описание

Хеш-строка bcrypt имеет вид:

$ 2b $ [стоимость] $ [22-символьная соль] [31-символьный хеш]

Например:

$ 2a $ 10 $ N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy \ __ / \ / \ ____________________ / \ _____________________________ / Alg Cost Salt Hash:

$ 2 идентификатор алгоритма (bcrypt)

  • 10: коэффициент стоимости (2 ==>1024 раунда)
  • N9qo8uLOickgx2ZMRZoMye: 16-байтовая (128-битная) соль, кодировка base64 до 22 символов
  • IjZAgcfl7p92ldGxad68LJZdL17 24-байтовый (192-битный) хэш, кодировка base64 до 31 символа
  • Префикс «$ 2a $» или «$ 2b $» (или «$ 2y $») в строке хеша в теневом пароле Файл указывает, что строка хэша является хешем bcrypt в модульном формате шифрования. Остальная часть хеш-строки включает параметр стоимости, 128-битную соль (Radix-64, закодированную как 22 символа) и 192 бита результирующего хеш-значения (Radix-64 в кодировке 31 символ). Кодировка Radix-64 использует алфавит unix / crypt и не является «стандартной» Base-64. Параметр стоимости определяет количество итераций раскрытия ключа как степень двойки, которая является входом для алгоритма криптографии.

    Например, запись теневого пароля $ 2a $ 10 $ N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWyуказывает параметр стоимости 10, указывающий на 2 раунда расширения ключа. Соль будет N9qo8uLOickgx2ZMRZoMye, а результирующий хеш будет IjZAgcfl7p92ldGxad68LJZdL17lhWy. Согласно стандартной практике, сам пароль пользователя не сохраняется.

    История версий

    $ 2 $ (1999)

    Исходная спецификация Bcrypt определяла префикс $ 2 $. Это соответствует формату Modular Crypt Format, используемому при хранении паролей в файле паролей OpenBSD:

    • $ 1 $: крипта на основе MD5 ('md5crypt')
    • $ 2 $: крипта на основе Blowfish ('bcrypt')
    • $ sha1 $: крипта на основе SHA-1 ('sha1crypt')
    • $ 5 $: на основе SHA-256 crypt ('sha256crypt')
    • $ 6 $: крипта на основе SHA-512 ('sha512crypt')

    $ 2a $

    Исходная спецификация не определяла, как обрабатывать символы, отличные от ASCII, или как обрабатывать нулевой терминатор. Спецификация была изменена, чтобы указать, что при хешировании строк:

    • строка должна быть в кодировке UTF-8
    • должен быть включен нулевой терминатор

    С этим изменением версия была изменена на $ 2 a $

    $ 2x $, $ 2y $ (июнь 2011 г.)

    В июне 2011 г. ошибка была обнаружена в crypt_blowfish, PHP-реализации BCrypt. Это было неправильное обращение с символами с 8-битным набором. Они предложили системным администраторам обновить существующую базу паролей, заменив $ 2a $на $ 2x $, чтобы указать, что эти хэши плохие (и необходимо использовать старый сломанный алгоритм). Они также предложили идею о том, чтобы crypt_blowfish испускал $ 2y $для хэшей, сгенерированных фиксированным алгоритмом.

    Никто другой, включая каноническую OpenBSD, не принял идею 2x / 2y. Это изменение маркера версии было ограничено crypt_blowfish .

    $ 2b $ (февраль 2014 г.)

    В реализации bcrypt в OpenBSD была обнаружена ошибка. Они сохраняли длину своих строк в unsigned char (т.е. 8-битный байт). Если пароль был длиннее 255 символов, он переполнился бы и перешел на 255.

    BCrypt был создан для OpenBSD. Когда в их библиотеке обнаружилась ошибка, они решили поднять номер версии.

    Алгоритм

    Алгоритм bcrypt является результатом 64-кратного шифрования текста OrpheanBeholderScryDoubt с использованием Blowfish. В bcrypt обычная функция настройки клавиш Blowfish заменена дорогостоящей функцией настройки клавиш (EksBlowfishSetup):

    Функция bcrypt Ввод: стоимость: Число (4..31) log 2 (Итерации). например 12 ==>2 = 4096 итераций соль: массив байтов (16 байтов) случайная соль пароль: массив байтов (1..72 байта) пароль в кодировке UTF-8 Вывод: хэш: массив байтов ( 24 байта) // Инициализируем состояние Blowfish с помощью дорогостоящего алгоритма установки ключей // P: массив из 18 подключей (UInt32 [18]) // S: четыре блока подстановки (S-блоки), S 0...S 3. Каждый S-блок составляет 1024 байта (UInt32 [256]) P, S ← {\ displaystyle \ gets}\getsEksBlowfishSetup (cost, salt, password) // Неоднократно шифруйте текст «OrpheanBeholderScryDoubt» 64 раз ctext ← {\ displaystyle \ gets}\gets"OrpheanBeholderScryDoubt" // 24 байта ==>три 64-битных блока repeat (64) ctext ← {\ displaystyle \ gets}\getsEncryptECB (P, S, ctext) // шифрование с использованием стандартного Blowfish в режиме ECB // 24-байтовый ctext получается хеш пароля return Concatenate (cost, salt, ctext)

    Дорогая настройка ключа

    Алгоритм bcrypt сильно зависит от своего алгоритма настройки ключа «Eksblowfish», который работает следующим образом:

    Функция EksBlowfishSetup Вход: пароль: массив байтов (1..72 байта) Соль пароля в кодировке UTF-8: массив байтов (16 байтов) случайная стоимость соли: число (4..31) журнал 2 (итерации). например 12 ==>2 = 4096 итераций Вывод: P: массив UInt32, массив из 18 подключей на раунд S 1..S 4 : массив UInt32 массив из четырех SBox; каждый SBox равен 256 UInt32 (т.е. 1024 КБ) // Инициализируем P (подключи) и S (поля подстановки) шестнадцатеричными цифрами пи P, S ← {\ displaystyle \ gets}\getsInitialState () // Переставляем P и S на основе пароля и соли P, S ← {\ displaystyle \ gets}\getsExpandKey (P, S, salt, password) // Это "Дорогой »часть« Дорогой настройки ключа ». // В остальном настройка клавиш идентична Blowfish. повторить (2) P, S ← {\ displaystyle \ gets}\getsExpandKey (P, S, 0, пароль) P, S ← {\ displaystyle \ gets}\getsExpandKey (P, S, 0, salt) return P, S

    InitialState работает как в исходном алгоритме Blowfish, заполняя P-массив и S -Box записи с дробной частью π {\ displaystyle \ pi}\ pi в шестнадцатеричном формате.

    Клавиша раскрытия

    Функция ExpandKey выполняет следующие действия:

    Функция ExpandKey Ввод: пароль: массив байтов (1..72 байта) UTF -8 закодированная соль пароля: Байт [16] случайная соль P: массив UInt32 Массив из 18 подключей S 1..S 4 : UInt32 [1024] Четыре SBoxes по 1 КБ Вывод: P: массив UInt32 Массив из 18 подключей на раунд S 1..S 4 : UInt32 [1024] Четыре SBoxes по 1 КБ // Смешайте пароль в массив подключей P для n ← {\ displaystyle \ gets}\gets1 to18 doPn← {\ displaystyle \ gets}\getsPnxor password [32 (n-1).. 32n-1] // обрабатываем пароль как циклический // Рассматриваем 128-битную соль как две 64-битные половинки (размер блока Blowfish). saltHalf [0] ← {\ displaystyle \ gets}\getssalt [0..63] // Нижние 64 бита соли saltHalf [1] ← {\ displaystyle \ gets}\getssalt [64..127] // Верхние 64 бита соли // Инициализируем 8-байтовый (64-битный) буфер всеми нулями. block ← {\ displaystyle \ gets}\gets0 // Смешиваем внутреннее состояние с P-блоками для n ← {\ displaystyle \ gets}\gets1 to9 do// 64-битный блок xor с 64-битным полублоком соли ← {\ displaystyle \ gets}\getsblock xor saltHalf [(n-1) mod 2] // каждая итерация чередуется между saltHalf [0 ] и saltHalf [1] // шифрование блока с использованием текущего ключевого блока расписания ← {\ displaystyle \ gets}\getsEncrypt (P, S, block) P 2n← {\ displaystyle \ gets}\getsblock [0..31] // младшие 32 бита блока P 2n + 1 ← {\ displaystyle \ gets}\getsblock [32..63] // верхний 32-битный блок // Смешивание зашифрованного состояния с внутренними S-блоками состояния для i ← {\ displaystyle \ gets}\gets1 to4 doдля n ← {\ displaystyle \ gets}\gets0 to127 do block ← {\ displaystyle \ gets}\getsEncrypt (state, block xor salt [64 (n-1).. 64n-1]) // как указано выше S i [2n] ← {\ displaystyle \ gets}\getsblock [0..31] // младшие 32 бита S i [2n + 1] ← {\ displaystyle \ g ets}\getsblock [32..63] // старшие 32 бита возвращают state

    Следовательно, ExpandKey (state, 0, key)- то же самое, что и обычное расписание ключей Blowfish, поскольку все операции XOR с нулевым значением соли неэффективны. ExpandKey (state, 0, salt)аналогичен, но использует соль как 128-битный ключ.

    Пользовательский ввод

    Многие реализации bcrypt усекают пароль до первых 72 байтов, следуя реализации OpenBSD.

    Сам математический алгоритм требует инициализации 18 32-битными подключами (что эквивалентно 72 октетам / байтам). Исходная спецификация bcrypt не требует какого-либо конкретного метода для отображения текстовых паролей из пользовательской среды в числовые значения для алгоритма. Один краткий комментарий в тексте упоминает, но не требует, возможность простого использования значения в кодировке ASCII символьной строки: «Наконец, ключевой аргумент - это секретный ключ шифрования, который может быть выбранным пользователем паролем до 56 байтов (включая завершающий нулевой байт, когда ключ является строкой ASCII). "

    Обратите внимание, что в приведенной выше цитате упоминаются пароли" до 56 байтов ", хотя сам алгоритм использует 72-байтовое начальное значение. Хотя Прово и Мазьер не указывают причину более короткого ограничения, они, возможно, были мотивированы следующим утверждением из исходной спецификации Blowfish Брюса Шнайера : «Предел 448 [бит] на размер ключа гарантирует, что [sic ] каждый бит каждого подключа зависит от каждого бита ключа ».

    Реализации изменили свой подход к преобразованию паролей в начальные числовые значения, включая иногда сокращение надежность паролей, содержащих символы, отличные от ASCII.

    Критика

    Максимальная длина пароля

    BCrypt имеет максимальную длину пароля 72 байта. Этот максимум получается из первой операции функции ExpandKey, которая xor18 4-байтовых подключей (P) с паролем:

    P1..P 18← {\ displaystyle \ gets}\getsP1..P 18 xor passwordBytes

    Пароль (в кодировке UTF-8) повторяется до 72 байтов. Например, пароль:

    правильная скоба аккумулятора лошади(29 байтов)

    Повторяется до тех пор, пока он не совпадет с 72 байтами из 18 P на раунд подключей:

    правильный скоба конского аккумулятора правильная скоба конского аккумулятора правильная лошадь(72 байта)

    Это также означает, что если пароль был длиннее 72 байтов в кодировке UTF-8: пароль был бы усечен. Для некоторых символов может потребоваться 4 байта при кодировке UTF-8. Это означает, что в худшем случае это может ограничить пароль до 18 символов:

    𐑜𐑝𐑟𐑥𐑷𐑻𐑽𐑾𐑿𐑿𐑰𐑩𐑛𐑙𐑘𐑙𐑒𐑔(18 символов, 72 байта)

    Этот предел 72-байтовых паролей (18 подключей * 4- байтов каждый) можно было адресовать несколькими способами:

    Решение 1 - Увеличить количество подключей

    Вы можете увеличить количество P подключей и, следовательно, увеличить максимальную длину доступного пароля. Брюс Шнайер, первоначальный автор Blowfish, заметил, что люди могут играть с добавлением большего количества раундов, что требует большего количества подключей, что для bcrypt увеличивает максимальную длину пароля. Обратной стороной этого является то, что по-прежнему существует максимальная длина пароля, а не максимальная длина.

    Решение 2. Продолжайте xили смешивать ключевые байты в массив подключей P

    Смешивание паролей продолжается только до тех пор, пока P 1... P 18. Когда вы достигли P18и у вас остались необработанные байты пароля, продолжите процесс xor на P1. Обратной стороной этого подхода является то, что время вычисления приводит к утечке длины пароля (утечка информации побочного канала).

    Решение 3 - Предварительный хэш-пароль

    Длинный пароль может быть предварительно хеширован с помощью другой криптографической хеш-функции. Эта функция всегда выводит дайджест фиксированного размера. Пока результирующий дайджест меньше 72 байтов: его можно передать в bcrypt без обрезания. Это подход, используемый DropBox и другими. Например, рассмотрим пароль:

    ਤੇਜ਼ ਭੂਰੇ ਲੂੰਬੜ ਨੇ ਆਲਸੀ ਕੁੱਤੇ ਉੱਤੇ ਛਾਲ ਮਾਰ ਦਿੱਤੀ(32 символа, 126 байт)

    Если вы хешируете этот пароль с помощью SHA-256, вы получите 256 -битный (32-байтовый) дайджест:

    A7 B2 AA 86 CB 57 D3 08 EA 54 9F 34 E5 91 7E 8C 06 9B D0 0D 34 28 B1 CA 8D 71 B2 2E 84 DA C0 F8

    Кодировка дайджеста Base64 дает строку из 44 символов:

    p7KqhstX0wjqVJ805ZF + jAab0A00KLHKjXGyLoTawPg =(44 символа, 44 байта)

    и всегда соответствует 72-байтовому пределу bcrypt..

    Этот подход аналогичен подходу, используемому Pufferfisdiv class="ht", усовершенствованной версией bcrypt с усиленным кешированием, которая использует HMAC SHA-152 для преобразования пароля в фиксированную длину. 64-байтовый (512-битный) ключ.

    Усечение хэша пароля

    Алгоритм bcrypt включает в себя многократное шифрование 24-байтового текста:

    OrpheanBeholderScryDoubt(24 байта)

    Это генерирует 24 байта зашифрованного текста, например:

    85 20 af 9f 03 3d b3 8c 08 5f d2 5e 2d aa 5e 84 a2 b9 61 d2 f1 29 c9 a4(24 байта)

    который тогда должен получить radix-64, закодированный до 32 символов:

    hSCvnwM9s4wIX9JeLapehKK5YdLxKcmk(32 символа)

    Но каноническая реализация OpenBSD усекает хэш пароля до 23 байтов:

    85 20 af 9f 03 3d b3 8c 08 5f d2 5e 2d aa 5e 84 a2 b9 61 d2 f1 29 c9a4(23 байта)

    и результирующий текст в кодировке base-64, который обычно будет:

    hSCvnwM9s4wIX9JeLapehKK5YdLxKck =

    имеет завершающий = удален, оставляя хэш:

    hSCvnwM9s4wIX9JeLapehKK5YdLxKck

    Непонятно, почему каноническая реализация удаляет 8 бит из полученный хеш пароля.

    Использование нестандартной кодировки base64

    Кодировка base-64, используемая канонической реализацией OpenBSD, использует словарь кодирования base-64, который отличается от словаря, доступного почти для всех языков и платформ. Кодировка совместима с crypt . Это означает, что кодировка несовместима с RFC 4648.

    См. Также
    • Портал бесплатного программного обеспечения с открытым исходным кодом
    Ссылки
    Внешние ссылки
    Последняя правка сделана 2021-05-12 08:14:54
    Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
    Обратная связь: support@alphapedia.ru
    Соглашение
    О проекте