SHA-3 и семейство Keccak

SHA-3 основан на алгоритме Keccak, разработанном Гвидо Бертоне, Жоаном Даменом, Михаэлем Пеетерсом и Жилем Ван Ассхе. В отличие от предыдущих стандартов семейства SHA (SHA-1, SHA-2), использующих конструкцию Меркла–Дамгарда, Keccak построен на принципиально иной модели — sponge construction (губчатая конструкция).

Губчатая конструкция оперирует внутренним состоянием фиксированного размера и выполняет две фазы:

  • Absorbing (поглощение) — входные данные «впитываются» во внутреннее состояние
  • Squeezing (выжимка) — из состояния извлекается выходной хэш произвольной длины

Внутреннее состояние Keccak представлено как трёхмерный массив битов, обычно обозначаемый как:

A[x][y][z]

где:

  • x, y — координаты в плоскости 5×5
  • z — глубина (битовая длина слова)

Общий размер состояния обозначается как b (например, 1600 бит для SHA-3).


Параметры: bitrate и capacity

Ключевыми параметрами являются:

  • r (bitrate) — количество бит, используемых для обработки входных данных
  • c (capacity) — оставшаяся часть состояния, обеспечивающая криптостойкость

Связь:

b = r + c

Для SHA-3:

Алгоритм r c Выход
SHA3-224 1152 448 224
SHA3-256 1088 512 256
SHA3-384 832 768 384
SHA3-512 576 1024 512

Чем больше c, тем выше устойчивость к атакам, но ниже производительность.


Раундовая функция Keccak-f

Основой алгоритма является перестановка Keccak-f[b], состоящая из последовательности раундов. Для b = 1600 используется 24 раунда.

Каждый раунд включает 5 шагов:

1. θ (theta)

Диффузия между столбцами:

  • Для каждого столбца вычисляется XOR всех элементов
  • Результат влияет на соседние столбцы

2. ρ (rho)

Побитовые циклические сдвиги:

  • Каждый элемент состояния сдвигается на фиксированное количество бит

3. π (pi)

Перестановка координат:

  • Элементы перемещаются по фиксированной схеме

4. χ (chi)

Нелинейное преобразование:

  • Каждый бит зависит от соседних по строке

5. ι (iota)

Добавление раундовой константы:

  • XOR с фиксированным значением для предотвращения симметрий

Padding (дополнение данных)

Перед обработкой данные дополняются до кратности r. Используется схема:

pad10*1

Это означает:

  • добавление 1
  • затем нулей
  • и завершающего 1

Для SHA-3 добавляется также доменный разделитель:

  • SHA-3: 0x06
  • Keccak (оригинальный): 0x01

Это отличие делает SHA-3 несовместимым с «чистым» Keccak.


Отличия SHA-3 от SHA-2

Характеристика SHA-2 SHA-3 (Keccak)
Конструкция Меркл–Дамгард Sponge
Уязвимость к length extension Да Нет
Параллелизм Ограниченный Лучше масштабируется
Гибкость выхода Фиксированный Произвольный

Реализация в CryptoJS

Библиотека crypto-js предоставляет поддержку SHA-3, но важно учитывать: реализация соответствует Keccak, а не финальному стандарту NIST SHA-3.

Подключение

import CryptoJS from "crypto-js";

или

const CryptoJS = require("crypto-js");

Базовое использование SHA-3

const hash = CryptoJS.SHA3("Hello, world!");
console.log(hash.toString());

По умолчанию используется длина 512 бит.


Выбор длины хэша

const hash224 = CryptoJS.SHA3("data", { outputLength: 224 });
const hash256 = CryptoJS.SHA3("data", { outputLength: 256 });
const hash384 = CryptoJS.SHA3("data", { outputLength: 384 });
const hash512 = CryptoJS.SHA3("data", { outputLength: 512 });

Параметр outputLength управляет размером результата.


Работа с форматами данных

Строки

CryptoJS.SHA3("text").toString();

WordArray

const wordArray = CryptoJS.enc.Utf8.parse("text");
const hash = CryptoJS.SHA3(wordArray);

Hex

hash.toString(CryptoJS.enc.Hex);

Инкрементальное хэширование

Позволяет обрабатывать данные частями:

const sha3 = CryptoJS.algo.SHA3.create();

sha3.update("Hello");
sha3.update(", ");
sha3.update("world");

const hash = sha3.finalize();

Полезно при работе с потоками или большими файлами.


HMAC с использованием SHA-3

const hmac = CryptoJS.HmacSHA3("message", "secret");
console.log(hmac.toString());

С параметрами:

const hmac = CryptoJS.HmacSHA3("message", "secret", {
    outputLength: 256
});

Внутреннее представление WordArray

CryptoJS использует структуру WordArray:

  • массив 32-битных слов
  • длина в байтах (sigBytes)

Пример:

const data = CryptoJS.enc.Hex.parse("deadbeef");

Производительность и особенности

  • SHA-3 медленнее SHA-2 на большинстве CPU
  • лучше подходит для аппаратных реализаций
  • устойчив к атакам расширения длины
  • поддерживает произвольную длину выхода (в теории)

SHAKE: расширяемые функции вывода (XOF)

Keccak также поддерживает SHAKE:

  • SHAKE128
  • SHAKE256

В CryptoJS напрямую не реализованы, но концептуально:

  • нет фиксированной длины выхода
  • можно «выжимать» сколько угодно бит

Практические сценарии

Хэширование паролей (не рекомендуется напрямую)

CryptoJS.SHA3(password).toString();

Лучше использовать:

  • PBKDF2
  • bcrypt
  • scrypt

Проверка целостности

const fileHash = CryptoJS.SHA3(fileContent).toString();

Подписи сообщений

const signature = CryptoJS.HmacSHA3(message, key);

Ограничения CryptoJS SHA-3

  • реализует Keccak, а не стандарт NIST SHA-3
  • несовместим с системами, ожидающими строгий SHA-3
  • нет поддержки SHAKE

Отличие Keccak и SHA-3 на практике

CryptoJS.SHA3("abc").toString();

Результат будет отличаться от:

SHA3-256("abc") по стандарту NIST

Причина — различный padding (доменный разделитель).


Рекомендации по использованию

  • использовать SHA-3 в новых системах при отсутствии требований совместимости
  • учитывать различие между Keccak и SHA-3
  • задавать outputLength явно
  • избегать прямого использования для хранения паролей

Глубокое понимание sponge-конструкции

Состояние делится на:

  • rate (r) — доступная часть
  • capacity (c) — скрытая часть

Во время absorbing:

state[0:r] ^= input_block

Затем применяется permutation.

Во время squeezing:

output = state[0:r]

При необходимости — повтор permutation.


Безопасность

Уровень безопасности определяется c:

security ≈ c / 2

Например:

  • SHA3-256 → c = 512 → ~256 бит стойкости

Итоговая структура алгоритма

  1. Инициализация состояния нулями
  2. Padding входных данных
  3. Absorbing (поглощение блоков)
  4. Применение Keccak-f
  5. Squeezing (выходной хэш)

Минимальный пример с параметрами

const hash = CryptoJS.SHA3("Hello", {
    outputLength: 256
});

console.log(hash.toString(CryptoJS.enc.Hex));

Расширенный пример с HMAC

const hmac = CryptoJS.HmacSHA3("Important message", "key123", {
    outputLength: 512
});

console.log(hmac.toString());

Контроль различий через тест

console.log(CryptoJS.SHA3("abc", { outputLength: 256 }).toString());

Сравнение с эталонными SHA-3 значениями выявит несовпадение из-за Keccak-паддинга.


Внутренний цикл Keccak (упрощённо)

for each round:
    θ → ρ → π → χ → ι

Эта последовательность обеспечивает:

  • диффузию
  • нелинейность
  • устойчивость к криптоанализу

Применение в современных системах

  • блокчейн (Ethereum использует Keccak-256)
  • цифровые подписи
  • хэш-таблицы с высокой стойкостью
  • генераторы случайных чисел

Связь с Ethereum

В Ethereum используется:

Keccak-256 (не SHA3-256!)

Это совпадает с реализацией CryptoJS, что делает библиотеку полезной для Web3-разработки.


Вывод ключевых свойств

  • sponge-конструкция вместо Merkle-Damgård
  • высокая гибкость
  • устойчивость к современным атакам
  • различие между Keccak и SHA-3 критично для совместимости