- Что из себя представляет sha-3?
- 1 этап: дополнение
- 2 этап: размер состояния
- 3 этап: функция впитывания
- Password_hash()
- Алгоритм :
- Алгоритм перестановок:
- История
- Криптоустойчивость sha-3
- Матчасть (короткая)
- Момент случайности
- О хэшировании
- Процесс майнинга
- Резюме
- Скорость хэширования
- Шаг :
- Шаг :
- Шаг 1 — предварительная работа
- Шаг 5 — созданием расписание сообщений (w)
- Шаг 6 — сжатие
Что из себя представляет sha-3?
SHA-3 является важным криптографическим алгоритмом для обеспечения информационной безопасности, а также целостности данных в цифровых операциях. Недавние безопасные хеш-алгоритмы, включая MD5, RIPEMD, SHA-0, SHA-1 и SHA-2 устарели и были признаны восприимчивыми к атакам различного рода.
SHA-3 (Keccak) – алгоритм хеширования переменной разрядности, разработанный группой во главе с Йоаном Дайменом в 2021 году. 5 августа 2021 года алгоритм утверждён и опубликован в качестве стандарта FIPS 202. Keccak был выбран в качестве официального алгоритма для SHA-3 в 2021 году.
Алгоритмы MD(x) основаны на методе вычислений в цикле с использованием простых логических операций типа OR, XOR, AND, NOT. поэтому становится возможным построение коллизий с одинаковым, заранее выбранным префиксом. Однако, как показало время алгоритмы MD(x) перестали быть безопасными из-за программ, способных находить коллизии за сравнительно небольшое время.
Губка — это итеративная конструкция для создания функции с произвольной длиной на входе и произвольной длиной на выходе на основе преобразований перестановки.
Алгоритм получения выходного значения хеш-функции с помощью алгоритма SHA-3 можно разделить на несколько этапов:
1 этап: дополнение
Этот начальный шаг аналогичен многим алгоритмам хеширования. Прежде чем мы сможем начать хешировать наше сообщение, мы должны убедиться, что оно имеет стандартную длину (добиваемся определенной кратности), и для этого мы выполняем процесс дополнения.
Прежде чем приступить, нужно узнать, каков стандартный размер, которому стоит соответствовать, и для этого рассмотрим, как Keccak вычисляет размер состояния.
Для SHA-3 значение l принимается равным 6. Чем больше размер, тем выше безопасность, которую он обеспечивает. Теперь, основываясь на значении “
Теперь мы знаем, что для SHA-3 размер состояния будет равен 1600 битам, а количество раундов вычислений – 24.
Возвращаясь к дополнению, нам нужно добавить биты к сообщению в зависимости от длины хеша, который предстоит вычислить.
Дополнение должно быть сделано таким образом, чтобы длина дополненного сообщения была кратна “
2 этап: размер состояния
Сумма значений ‘
Далее алгоритм можно условно разделить на две условные части: “впитывание” и “отжимание”.
3 этап: функция впитывания
Каждый блок
Password_hash()
Несмотря на высокий уровень безопасности, обеспечиваемый функцией crypt(), многие считают её слишком сложной, из-за чего программисты часто допускают ошибки. Вместо неё некоторые разработчики используют для генерирования хэшей комбинации слабых алгоритмов и слабых солей:
Функция password_hash() существенно облегчает разработчику жизнь и повышает безопасность кода. Для хэширования пароля достаточно скормить его функции, и она вернёт хэш, который можно поместить в БД:
И всё! Первый аргумент — пароль в виде строки, второй аргумент задаёт алгоритм генерирования хэша. По умолчанию используется bcrypt, но при необходимости можно добавить и более сильный алгоритм, который позволит генерировать строки большей длины. Если в своём проекте вы используете PASSWORD_DEFAULT, то удостоверьтесь, что ширина колонки для хранения хэшей не менее 60 символов.
Обратите внимание, что вам не нужно задавать значение соли или стоимостного параметра. Новый API всё сделает за вас. Поскольку соль является частью хэша, то вам не придётся хранить её отдельно. Если вам всё-таки нужно задать своё значение соли (или стоимости), то это можно сделать с помощью третьего аргумента:
Всё это позволит вам использовать самые свежие средства обеспечения безопасности. Если в дальнейшем в PHP появится более сильный алгоритм хэширования, то ваш код станет использовать его автоматически.
Алгоритм :
Для всех , таких, что
Пусть – массив длинны , заполненный нулями
Для от 0 до :
Для массива в стороку длины
Алгоритм перестановок:
Перевод строки в массив
Для от до
Перевод массива в строку длины
4 этап: Функция отжимания
Пока длина меньше
История
До недавнего времени индустрия шифрования использовала два алгоритма в цифровых сертификатах. Первый алгоритм шифрования называется RSA, второй — алгоритм хэширования — SHA-1, оба в данный момент считается неустойчивыми из-за прогресса в области криптоанализ.
Устойчивость и эффективность работы алгоритма RSA зависит от размера ключа, чем больше ключ тем устойчивее и медленнее шифрование. Прогресс в области криптоанализа привел к увеличению размера ключей, используемых с алгоритмом, что повысило требования к вычислительным мощностям, нужных для поддержания достаточной устойчивости алгоритма.
Поэтому в январе 2021 года доверенные центры авторизации решили принять в работу рекомендации NIST (Национального института стандартов и технологий) и обеспечивать все новые RSA-сертификаты ключами с длиной не менее 2048 бит. В 1998 году компания GlobalSign одной из первых в качестве центра авторизации реализовала ключи с размером 2048 бит в своих цифровых сертификатах, с тех пор центры сертификации стремились следовать этим рекомендациям.
К сожалению, размеры ключей не могут расти постоянно, особенно если, как мы надеемся, протокол SSL будет использоваться для большинства трафика в Интернете — будет затрачиваться слишком много вычислительных ресурсов.
Затем стал использоваться алгоритм SHA-1. Алгоритмы хэширования SHA-1 на входе получают данные различного размера и уменьшают их до определенной и фиксированной длины, в результате на выходе получается уникальный идентификатор входных данных. Следует учитывать, что алгоритмы хэширования всегда подвержены коллизиям, а прогресс в области криптоанализа сделал появление подобных коллизий более вероятным.
Криптоустойчивость sha-3
Семейство хеш-функций Keccak было подвергнуто интенсивному криптоанализу с момента его представления на конкурс SHA-3 в 2008 [5]. В 2021 году Национальный институт стандартов и технологий США выбрал Keccak победителем конкурса SHA-3.
Подробно сосредоточимся на коллизиях семейства Keccak, то есть на поиске двух разных исходных сообщениях, дающих разное значение хеша. Лучшие предыдущие практические атаки столкновений на семейство Keccak-это Keccak -224 и KECCAK -256, уменьшенные до 4 раундов, найденных Dinur l.[3] в 2021 году и позже представлен в журнальной версии [4]. После этого теоретические результаты улучшились до 5-раундового KECCAK -256. Однако на практике количество раундов остается на уровне 4. Чтобы продвинуть криптоанализ Keccak, команда разработчиков алгоритма предложила уменьшить количество раундов в Keccak challenge [6] т.е рассматривать хеш с размером 160 для атаки с по поиску коллизий и хеш размером 80 для атаки прообраза с каждым из 4 размеров внутренних состояний (state size в 1 шаге дополнения) , уменьшенных до 12 раундов т.е.
Теоретическая оценка результатов по поиску коллизий на сервере с 32 ядрами процессоров AMD. Таблица взята из источника [2]
Теперь перейдем к рассмотрению алгебраических методов для установки атак прообразов на несколько вариантов Keccak, основанных на свойствах χ шага и линейных перестановок
Основная идея атак состоит в том, чтобы установить и решить линейные уравнения. Сложность в этом разделе измеряется количеством решений для линейной системы уравнений.
Далее последует представление атак прообразов, в зависимости от выбора линейных структур и способы инвертирования Sbox с последующим анализом сложности. Основная идея подобных атак состоит в том, чтобы установить и решить соответствующие системы линейных уравнений.
SHAKE128
Данные взяты из источника [7]
Устанавливаем
Данные взяты из источника [7]
Все эти 6×64 линейных уравнения линейно независимы и, таким образом, имеют
Матчасть (короткая)
Hash = хеш функция — (свертка) функция однозначного отображения строки (любой длины) на конечное множество (строку заданной длины).
Само число (строка) хеш — результат вычисления хеш-функции над данными.
Существуют криптографические и некриптографические (классифицируются отдельно, к ним относятся, например, контрольные суммы) хеш-функции.
Для криптографических хэшей есть три дополнительных условия, которые отличают их от всех остальных:
Подробнее —
Вникать в тонкости криптографии прикладному разработчику не обязательно, достаточно запомнить какие хэш-функции (алгоритмы по названию) можно сейчас использовать, а какие уже нет. MD5 — уже нельзя, коллеги, — используйте bcrypt/scrypt.
В веб-приложениях, в числе прочего, хеш-функции используются для безопасного хранения секретов (паролей) в базе данных.Именно хэш-функция становится вашим последним оплотом, если злоумышленник смог свести нападение к локальной атаке на систему аутентификации. Про онлайн атаки (перебор паролей НТТР запросами), может быть, кто-то еще напишет позже.
Ниже перечислены требования, которым ваш хеш в базе должен удовлетворять:
Для выполнения первого требования нужно использовать стойкие в настоящее время (а не в 90х годах!) хеш-функции.Для выполнения второго — к паролю перед хешированием добавляется случайная строка (соль). Таким образом, у двух пользователей с паролем «123456» будут разные соли «соль1» и «соль2», а соответственно и хеш-функции от «123456соль1» и «123456соль2» в базе тоже будут разные.
Теперь немного про систему хранения — и соль и сам хеш хранятся в базе данных.То есть получив доступ к СУБД, злоумышленник получает и значения хешей и соли.
Момент случайности
Для генерирования подходящей соли нам нужен хороший генератор случайных чисел. Сразу забудьте о функции rand().
Есть замечательная статья, посвящённая этому вопросу. Вкратце: компьютер сам по себе не генерирует случайные данные, это детерминированная машина. То есть каждый выполняемый алгоритм, получив несколько раз на входе одни и те же данные, на выходе представит один и тот же результат.
Когда от компьютера хотят случайное число, то обычно он берёт данные из нескольких источников (например, переменные среды: дату, время, количество записанных/считанных байтов и т. д.), а затем производит над ними вычисления для получения «случайных» данных.
Если псевдослучайный генератор ещё и реализован неправильно, то в генерируемых им данных можно обнаружить паттерны, а с их помощью предсказать результат генерирования. Взгляните на эту картинку, представляющую собой результат работы PHP-функции rand():
А теперь сравните с данными, сгенерированными полноценным генератором случайных чисел:
К сожалению, ни rand(), ни mt_rand() нельзя считать подходящими инструментами для обеспечения высокого уровня безопасности.
Если вам нужно получить случайные данные, воспользуйтесь функцией openssl_random_pseudo_bytes(), которая доступна начиная с версии 5.3.0. У неё даже есть флаг crypto_strong, который сообщит о достаточном уровне безопасности.
Пример использования:
О хэшировании
В настоящее время практически ни одно приложение криптографии не обходится без использования хэширования.
Хэш-функции – это функции, предназначенные для «сжатия» произвольного сообщения или набора данных, записанных, как правило, в двоичном алфавите, в некоторую битовую комбинацию фиксированной длины, называемую сверткой. Хэш-функции имеют разнообразные применения при проведении статистических экспериментов, при тестировании логических устройств, при построении алгоритмов быстрого поиска и проверки целостности записей в базах данных.
Криптографической хеш-функцией называется всякая хеш-функция, являющаяся криптостойкой, то есть удовлетворяющая ряду требований специфичных для криптографических приложений. В криптографии хэш-функции применяются для решения следующих задач:
— построения систем контроля целостности данных при их передаче или хранении,
— аутентификация источника данных.
Хэш-функцией называется всякая функция h:X -> Y, легко вычислимая и такая, что для любого сообщения M значение h(M) = H (свертка) имеет фиксированную битовую длину. X — множество всех сообщений, Y — множество двоичных векторов фиксированной длины.
Как правило хэш-функции строят на основе так называемых одношаговых сжимающих функций y = f(x1, x2) двух переменных, где x1, x2 и y — двоичные векторы длины m, n и n соответственно, причем n — длина свертки, а m — длина блока сообщения.
Для получения значения h(M) сообщение сначала разбивается на блоки длины m (при этом, если длина сообщения не кратна m то последний блок неким специальным образом дополняется до полного), а затем к полученным блокам M1, M2,.., MN применяют следующую последовательную процедуру вычисления свертки:
Ho = v,Hi = f(Mi,Hi-1), i = 1,.., N,h(M) = HN
Здесь v — некоторая константа, часто ее называют инициализирующим вектором. Она выбираетсяиз различных соображений и может представлять собой секретную константу или набор случайных данных (выборку даты и времени, например).При таком подходе свойства хэш-функции полностью определяются свойствами одношаговой сжимающей функции.
Выделяют два важных вида криптографических хэш-функций — ключевые и бесключевые. Ключевые хэш-функции называют кодами аутентификации сообщений. Они дают возможность без дополнительных средств гарантировать как правильность источника данных, так и целостность данных в системах с доверяющими друг другу пользователями.
Бесключевые хэш-функции называются кодами обнаружения ошибок. Они дают возможность с помощью дополнительных средств (шифрования, например) гарантировать целостность данных. Эти хэш-функции могут применяться в системах как с доверяющими, так и не доверяющими друг другу пользователями.
Процесс майнинга
Примечание: в этом разделе мы будем говорить о выработке биткоинов.
Когда протокол Биткоина хочет добавить новый блок в цепочку, майнинг – это процедура, которой он следует. Всякий раз, когда появляется новый блок, все их содержимое сначала хэшируется. Если подобранный хэш больше или равен, установленному протоколом уровню сложности, он добавляется в блокчейн, а все в сообществе признают новый блок.
Однако, это не так просто. Вам должно очень повезти, чтобы получить новый блок таким образом. Так как, именно здесь присваивается уникальный символ. Уникальный символ (nonce) — это одноразовый код, который объединен с хэшем блока. Затем эта строка вновь меняется и сравнивается с уровнем сложности.
Подводя итоги:
• Выполняется хэш содержимого нового блока.• К хэшу добавляется nonce (специальный символ).• Новая строка снова хэшируется.• Конечный хэш сравнивается с уровнем сложности, чтобы проверить меньше он его или нет• Если нет, то nonce изменяется, и процесс повторяется снова.
Помните номер свойства 6 хэш-функций? Удобство использования задачи?Для каждого выхода «Y», если k выбран из распределения с высокой мин-энтропией, невозможно найти вход x таким образом, H (k | x) = Y.
Так что, когда дело доходит до майнинга биткоинов:
• К = Уникальный символ• x = хэш блока• Y = цель проблемы
Весь процесс абсолютно случайный, основанный на генерации случайных чисел, следующий протоколу Proof Of Work и означающий:
Что такое скорость хэширования?
Скорость хэширования в основном означает, насколько быстро эти операции хэширования происходят во время майнинга. Высокий уровень хэширования означает, что в процессе майнинга участвуют всё большее количество людей и майнеров, и в результате система функционирует нормально.
Резюме
На самом деле цифровые сертификаты не так сложны в понимании. Доверенная публичная организация, такая как центр сертификации центр сертификации GlobalSign, проверяет определенную выборку свидетельств, чтобы сформировать электронный идентификатор, который будет служить доказательством того, что была проведена проверка подлинности физического лица или организации.
Цифровой сертификат содержит сведения о том, кому он был выдан и кем. Также некоторые центры авторизации в свою очередь проходят сертификацию по целой цепочке центров, и эти сведения входят в сертификат. Когда цифровой сертификат используется, например, для подписывания документов и программного обеспечения, эта информация хранится с подписанным объектом в безопасном и проверяемом формате и может быть использована для установления доверительной канала связи.
Как обычно и бывает, если копнуть поглубже, то все оказывается немного более сложным. В случае цифровых сертификатов действует и ряд других факторов. Например, какова квалификация третьей стороны, их методы работы, криптографические алгоритмы, использованные для формирования цифрового сертификата?
С точки зрения начальника управления информационной безопасности использование цифровых сертификатов, подобно SSL цифровых сертификатов, подобных SSL, может сказаться на рабочем процессе организации. Поэтому использование сертификата от центра сертификации подразумевает полное доверие методам, применяемым в центре.
Это особенно важно в отношении решений, касающихся используемых криптографических алгоритмов и длин ключей. К счастью не нужно быть криптоаналитиком, чтобы принимать хорошие решения по данным вопросам, но нужно базовое понимание темы, представление о грядущих переменах, и внимательное отношение к алгоритмам, которые предоставляют ряд центров сертификации, работающих на рынке безопасности в данный момент.
Скорость хэширования
Казалось бы — чем быстрее, тем лучше. Чем быстрее сгенерируется хэш, тем быстрее наш юзер сможет зарегистрироваться и начать уже приносить профит. Однако чем больше скорость хэширования, тем быстрее его сможет подобрать и хакер.
Современные ПК с мощными GPU, могут рассчитывать миллионы хэшей в секунду и больше. А это позволяет ломать пароли простым подбором, с помощью брутфорса-атак. Считаете что пароль в 8 символов достаточно безопасен? Если в пароле используются символы в нижнем и верхнем регистрах и цифры, то общее количество возможных символов составит 62 (26 26 10).
Для пароля длиной в 8 символов, существует 62^8 различных комбинаций (порядка 218 триллионов). Со скоростью в 1 миллиард хэшей в секунду (достаточно маленькая для брутфорс-атаки), пароль будет сломан примерно за 60 часов. А для наиболее распространенной длины пароля в 6 символов, длительность расшифровки составит меньше двух минут.
Можно конечно пренебречь пользователями, использующими короткие и простые пароли, или заставить всех в добровольно-принудительном порядке использовать 10-символьные пароли, со знаками препинания и символами шумерской клинописи. Но лучше использовать более медленные функции хэширования. Например можно замедлить функцию хэша вручную в 1000 раз с помощью следующего кода:
function myhash($password, $unique_salt) {
$salt = "f#@V)Hu^%Hgfds";
$hash = sha1($unique_salt . $password);
// увеличиваем время исполнения функции в 1000 раз, заставив функцию сперва выполниться 1000 раз, и только затем возвратить результат
for ($i = 0; $i < 1000; $i ) {
$hash = sha1($hash);
}
return $hash;
}
Шаг :
Для всех
Для всех
Шаг :
Введем дополнительную функцию
Если , то возвращается 1
Пусть
Для от 1 до 255:
Возвращается
Шаг 1 — предварительная работа
Преобразуем «Привет, мир» в двоичный код:
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100
Добавим 1:
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 1
Дополните код нулями, пока данные не станут равны 512 бит, минус 64 бита (в результате 448 бит):
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
Добавьте 64 бита в конец в виде целого числа с порядком байтов от старшего к младшему (big-endian), представляющего длину входного сообщения в двоичном формате. В нашем случае это 88, или «1011000».
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 01011000
Теперь у нас есть ввод, который будет делиться на 512 без остатка.
Шаг 5 — созданием расписание сообщений (w)
Скопируйте входные данные из шага 1 в новый массив, где каждая запись представляет собой 32-битное слово:
01101000011001010110110001101100 01101111001000000111011101101111
01110010011011000110010010000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000001011000
Добавьте еще 48 слов, инициализированных нулем, чтобы у нас получился массив w [0… 63]
01101000011001010110110001101100 01101111001000000111011101101111
01110010011011000110010010000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000001011000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
...
...
00000000000000000000000000000000 00000000000000000000000000000000
Измените обнуленные индексы в конце массива, используя следующий алгоритм:
Для
i
из w[16…63]:
Теперь посмотрим, как это работает для w [16]:
w[1] rightrotate 7:
01101111001000000111011101101111 -> 11011110110111100100000011101110
w[1] rightrotate 18:
01101111001000000111011101101111 -> 00011101110110111101101111001000
w[1] rightshift 3:
01101111001000000111011101101111 -> 00001101111001000000111011101101
s0 = 11011110110111100100000011101110 XOR 00011101110110111101101111001000 XOR 00001101111001000000111011101101
s0 = 11001110111000011001010111001011
w[14] rightrotate 17:
00000000000000000000000000000000 -> 00000000000000000000000000000000
w[14] rightrotate19:
00000000000000000000000000000000 -> 00000000000000000000000000000000
w[14] rightshift 10:
00000000000000000000000000000000 -> 00000000000000000000000000000000
s1 = 00000000000000000000000000000000 XOR 00000000000000000000000000000000 XOR 00000000000000000000000000000000
s1 = 00000000000000000000000000000000
w[16] = w[0] s0 w[9] s1
w[16] = 01101000011001010110110001101100 11001110111000011001010111001011 00000000000000000000000000000000 00000000000000000000000000000000
// addition is calculated modulo 2^32
w[16] = 00110111010001110000001000110111
В расписании сообщений осталось 64 слова (w):
01101000011001010110110001101100 01101111001000000111011101101111
01110010011011000110010010000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000001011000
00110111010001110000001000110111 10000110110100001100000000110001
11010011101111010001000100001011 01111000001111110100011110000010
00101010100100000111110011101101 01001011001011110111110011001001
00110001111000011001010001011101 10001001001101100100100101100100
01111111011110100000011011011010 11000001011110011010100100111010
10111011111010001111011001010101 00001100000110101110001111100110
10110000111111100000110101111101 01011111011011100101010110010011
00000000100010011001101101010010 00000111111100011100101010010100
00111011010111111110010111010110 01101000011001010110001011100110
11001000010011100000101010011110 00000110101011111001101100100101
10010010111011110110010011010111 01100011111110010101111001011010
11100011000101100110011111010111 10000100001110111101111000010110
11101110111011001010100001011011 10100000010011111111001000100001
11111001000110001010110110111000 00010100101010001001001000011001
00010000100001000101001100011101 01100000100100111110000011001101
10000011000000110101111111101001 11010101101011100111100100111000
00111001001111110000010110101101 11111011010010110001101111101111
11101011011101011111111100101001 01101010001101101001010100110100
00100010111111001001110011011000 10101001011101000000110100101011
01100000110011110011100010000101 11000100101011001001100000111010
00010001010000101111110110101101 10110000101100000001110111011001
10011000111100001100001101101111 01110010000101111011100000011110
10100010110101000110011110011010 00000001000011111001100101111011
11111100000101110100111100001010 11000010110000101110101100010110
Шаг 6 — сжатие
Инициализируйте переменные
a, b, c, d, e, f, g, h
и установите их равными текущим значениям хэш-функции соответственно
h0, h1, h2, h3, h4, h5, h6, h7
Запустите цикл сжатия, который изменит значения a… h. Выглядит он следующим образом:
Для i от 0 до 63
Совершим первую итерацию, сложение вычисляется по модулю 2 ^ 32:
a = 0x6a09e667 = 01101010000010011110011001100111
b = 0xbb67ae85 = 10111011011001111010111010000101
c = 0x3c6ef372 = 00111100011011101111001101110010
d = 0xa54ff53a = 10100101010011111111010100111010
e = 0x510e527f = 01010001000011100101001001111111
f = 0x9b05688c = 10011011000001010110100010001100
g = 0x1f83d9ab = 00011111100000111101100110101011
h = 0x5be0cd19 = 01011011111000001100110100011001
e rightrotate 6:
01010001000011100101001001111111 -> 11111101010001000011100101001001
e rightrotate 11:
01010001000011100101001001111111 -> 01001111111010100010000111001010
e rightrotate 25:
01010001000011100101001001111111 -> 10000111001010010011111110101000
S1 = 11111101010001000011100101001001 XOR 01001111111010100010000111001010 XOR 10000111001010010011111110101000
S1 = 00110101100001110010011100101011
e and f:
01010001000011100101001001111111
& 10011011000001010110100010001100 =
00010001000001000100000000001100
not e:
01010001000011100101001001111111 -> 10101110111100011010110110000000
(not e) and g:
10101110111100011010110110000000
& 00011111100000111101100110101011 =
00001110100000011000100110000000
ch = (e and f) xor ((not e) and g)
= 00010001000001000100000000001100 xor 00001110100000011000100110000000
= 00011111100001011100100110001100
// k[i] is the round constant
// w[i] is the batch
temp1 = h S1 ch k[i] w[i]
temp1 = 01011011111000001100110100011001 00110101100001110010011100101011 00011111100001011100100110001100 1000010100010100010111110011000 01101000011001010110110001101100
temp1 = 01011011110111010101100111010100
a rightrotate 2:
01101010000010011110011001100111 -> 11011010100000100111100110011001
a rightrotate 13:
01101010000010011110011001100111 -> 00110011001110110101000001001111
a rightrotate 22:
01101010000010011110011001100111 -> 00100111100110011001110110101000
S0 = 11011010100000100111100110011001 XOR 00110011001110110101000001001111 XOR 00100111100110011001110110101000
S0 = 11001110001000001011010001111110
a and b:
01101010000010011110011001100111
& 10111011011001111010111010000101 =
00101010000000011010011000000101
a and c:
01101010000010011110011001100111
& 00111100011011101111001101110010 =
00101000000010001110001001100010
b and c:
10111011011001111010111010000101
& 00111100011011101111001101110010 =
00111000011001101010001000000000
maj = (a and b) xor (a and c) xor (b and c)
= 00101010000000011010011000000101 xor 00101000000010001110001001100010 xor 00111000011001101010001000000000
= 00111010011011111110011001100111
temp2 = S0 maj
= 11001110001000001011010001111110 00111010011011111110011001100111
= 00001000100100001001101011100101
h = 00011111100000111101100110101011
g = 10011011000001010110100010001100
f = 01010001000011100101001001111111
e = 10100101010011111111010100111010 01011011110111010101100111010100
= 00000001001011010100111100001110
d = 00111100011011101111001101110010
c = 10111011011001111010111010000101
b = 01101010000010011110011001100111
a = 01011011110111010101100111010100 00001000100100001001101011100101
= 01100100011011011111010010111001
Все вычисления выполняются еще 63 раза, меняя переменные a-h. К счастью, мы не делаем это вручную. В итоге мы получили:
h0 = 6A09E667 = 01101010000010011110011001100111
h1 = BB67AE85 = 10111011011001111010111010000101
h2 = 3C6EF372 = 00111100011011101111001101110010
h3 = A54FF53A = 10100101010011111111010100111010
h4 = 510E527F = 01010001000011100101001001111111
h5 = 9B05688C = 10011011000001010110100010001100
h6 = 1F83D9AB = 00011111100000111101100110101011
h7 = 5BE0CD19 = 01011011111000001100110100011001
a = 4F434152 = 001001111010000110100000101010010
b = D7E58F83 = 011010111111001011000111110000011
c = 68BF5F65 = 001101000101111110101111101100101
d = 352DB6C0 = 000110101001011011011011011000000
e = 73769D64 = 001110011011101101001110101100100
f = DF4E1862 = 011011111010011100001100001100010
g = 71051E01 = 001110001000001010001111000000001
h = 870F00D0 = 010000111000011110000000011010000