Алгоритм SHA-512 в TweetNaCl.js

SHA-512 в TweetNaCl.js реализуется как функция криптографического хеширования фиксированной длины, возвращающая 64-байтный (512-битный) дайджест сообщения. В библиотеке она доступна через nacl.hash(message) и является частью минимального набора примитивов NaCl, используемых для получения криптографически стойких отпечатков данных.

В отличие от более сложных криптографических конструкций (шифрование, подписи), SHA-512 в данном контексте выполняет одну задачу — преобразование произвольного входного массива байт в детерминированную 512-битную последовательность, обладающую свойствами лавинного эффекта и устойчивостью к коллизиям.

Функция хеширования в TweetNaCl.js работает строго с байтовыми массивами:

  • вход: Uint8Array
  • выход: Uint8Array(64)

Любое сообщение, независимо от длины, преобразуется в фиксированный 64-байтный результат.

const hash = nacl.hash(new TextEncoder().encode("hello"));

Результат — бинарный массив, а не hex-строка. Преобразование в читаемый вид выполняется отдельно.

const hex = Array.from(hash)
  .map(b => b.toString(16).padStart(2, "0"))
  .join("");

Общая структура SHA-512

SHA-512 относится к семейству SHA-2 и работает с 64-битными словами. Это ключевое отличие от SHA-256, который оперирует 32-битными словами.

Основные характеристики:

  • размер блока: 1024 бита (128 байт)
  • размер слова: 64 бита
  • количество раундов: 80
  • размер хеша: 512 бит

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

Предобработка сообщения

Перед началом вычислений входное сообщение приводится к стандартному виду.

Дополнение (padding)

Сообщение дополняется следующим образом:

  1. добавляется бит 1 (0x80)
  2. затем добавляются нулевые байты
  3. в конец записывается длина исходного сообщения в битах (128-битное значение)

Итоговая длина становится кратной 1024 битам.

Этот шаг критичен: он гарантирует, что разные сообщения не могут иметь одинаковое внутреннее представление после разбиения на блоки.

Разбиение на блоки

После padding данные делятся на блоки по 128 байт:

M[0], M[1], ..., M[n]

Каждый блок интерпретируется как массив из 16 64-битных слов:

M[i] → W[0..15]

Инициализация хеш-значений

SHA-512 использует набор начальных значений (initial hash values), основанных на дробных частях квадратных корней простых чисел.

Внутреннее состояние состоит из восьми 64-битных переменных:

a, b, c, d, e, f, g, h

Инициализация задаётся фиксированными константами:

H0 = 6a09e667f3bcc908
H1 = bb67ae8584caa73b
H2 = 3c6ef372fe94f82b
H3 = a54ff53a5f1d36f1
H4 = 510e527fade682d1
H5 = 9b05688c2b3e6c1f
H6 = 1f83d9abfb41bd6b
H7 = 5be0cd19137e2179

Расширение сообщений (message schedule)

Каждый блок расширяется до 80 слов:

W[0..79]

Первые 16 слов берутся из блока, остальные вычисляются:

W[t] = σ1(W[t-2]) + W[t-7] + σ0(W[t-15]) + W[t-16]

где:

  • σ0, σ1 — битовые функции (циклические сдвиги и сдвиги вправо)

Основной цикл компрессии

Каждый из 80 раундов обновляет состояние:

T1 = h + Σ1(e) + Ch(e,f,g) + K[t] + W[t]
T2 = Σ0(a) + Maj(a,b,c)

h = g
g = f
f = e
e = d + T1
d = c
c = b
b = a
a = T1 + T2

Где используются функции:

  • Ch(x,y,z) = (x AND y) XOR (~x AND z)
  • Maj(x,y,z) = (x AND y) XOR (x AND z) XOR (y AND z)
  • Σ0, Σ1 — вращения битов

Константы K[t] (80 значений) также основаны на кубических корнях простых чисел.

Завершение обработки блока

После обработки одного блока результат добавляется к текущему состоянию:

H0 = H0 + a
H1 = H1 + b
...
H7 = H7 + h

После последнего блока все восемь значений конкатенируются, формируя 512-битный хеш.

Реализация в TweetNaCl.js

В TweetNaCl.js SHA-512 реализован в виде компактной функции nacl.hash.

Особенности реализации:

  • используется Uint8Array для всех операций
  • отсутствует потоковый интерфейс (вся обработка — одномоментная)
  • оптимизирована под минимальный размер кода
  • ориентирована на детерминированный результат без конфигурации

Пример использования:

import nacl from "tweetnacl";

const message = new TextEncoder().encode("cryptographic message");
const digest = nacl.hash(message);

Результат digest всегда имеет длину 64 байта.

Представление результата

Хеш SHA-512 часто используют в разных форматах:

бинарный

Uint8Array(64)

hex

128 символов шестнадцатеричного представления

base64

удобен для передачи в JSON и URL-safe контекстах

Особенности реализации в JavaScript

SHA-512 в TweetNaCl.js учитывает ограничения языка:

  • операции над 64-битными числами эмулируются через пары 32-битных значений
  • побитовые операции выполняются через | 0 и беззнаковую арифметику
  • отсутствует использование BigInt для совместимости и скорости

Это влияет на архитектуру реализации: алгоритм фактически превращается в набор строго оптимизированных операций над 32-битными регистрами.

Криптографические свойства

SHA-512 обеспечивает:

  • устойчивость к предобразу (preimage resistance)
  • устойчивость ко второму предобразу
  • устойчивость к коллизиям (в рамках 2^256 сложности)

В контексте TweetNaCl.js он используется как базовый строительный блок для:

  • хеширования сообщений
  • получения отпечатков данных
  • некоторых внутренних криптографических преобразований

Отличия SHA-512 от SHA-256 в контексте NaCl

Свойство SHA-256 SHA-512
размер слова 32 бита 64 бита
размер хеша 256 бит 512 бит
скорость на 64-bit CPU ниже выше
устойчивость высокая выше

SHA-512 предпочтителен в 64-битных средах, где он эффективнее обрабатывает большие объёмы данных.

Использование в криптографических схемах

Хотя SHA-512 сам по себе не является алгоритмом шифрования, он применяется как вспомогательная функция:

  • создание уникальных идентификаторов
  • контроль целостности
  • генерация фиксированных отпечатков сообщений перед дальнейшей криптографической обработкой

В TweetNaCl.js он сохраняет роль низкоуровневого примитива, на котором могут строиться более сложные конструкции.