Криптографические хеш-функции общего назначения проектируются для скорости и детерминированности. Их цель — быстро преобразовать произвольные данные в фиксированный отпечаток. В контексте паролей это становится проблемой: скорость, которая полезна в большинстве криптографических задач, превращается в уязвимость.
Парольное хеширование требует обратного набора свойств:
Алгоритмы вроде SHA-512 изначально не предназначены для этого класса задач.
В экосистеме TweetNaCl.js / nacl.js присутствует реализация хеш-функции, основанной на SHA-512:
nacl.hash(message)
или в более низкоуровневом виде:
nacl.hash = function(m) { ... } // SHA-512 over input
Этот механизм корректно выполняет задачу криптографического хеширования данных, но не содержит:
Фактически это чистая, быстрая функция без контрмер против атак на пароли.
Главная проблема SHA-512 в контексте паролей — производительность.
Современные GPU способны выполнять миллиарды SHA-512 операций в секунду. Это означает, что даже относительно сложный пароль становится уязвимым при атаке перебором.
Сценарий атаки выглядит так:
Отсутствие искусственного замедления делает такие атаки экономически выгодными.
SHA-512 сам по себе не предусматривает соль. В системах вроде TweetNaCl.js разработчик обязан добавлять её вручную.
Без соли возникает классическая уязвимость:
Пример небезопасного подхода:
const hash = nacl.hash(nacl.util.decodeUTF8(password));
Даже минимальное совпадение паролей становится статистически отслеживаемым.
Правильный подход требует уникальной соли на каждый пароль:
hash = SHA512(salt + password)
Но даже это не решает фундаментальную проблему скорости алгоритма.
TweetNaCl.js ориентирован на минимализм и реализацию проверенных криптопримитивов:
Отсутствует целый класс алгоритмов:
Причина заключается в философии библиотеки: она не предназначена для управления паролями, а только для криптографических строительных блоков.
Функция хеширования:
Функция вывода ключа (KDF):
SHA-512 не удовлетворяет этим требованиям.
Каждая проверка стоит дешево → огромная скорость перебора.
Используются базы утекших паролей и их комбинации.
Предрасчитанные таблицы соответствий «пароль → хеш», полностью эффективные при отсутствии соли.
Параллельная обработка делает SHA-512 практически неподходящим для защиты паролей.
Для хранения паролей используются специализированные алгоритмы:
const enc = new TextEncoder();
const key = await crypto.subtle.importKey(
"raw",
enc.encode(password),
"PBKDF2",
false,
["deriveBits"]
);
const derived = await crypto.subtle.deriveBits(
{
name: "PBKDF2",
salt: saltBuffer,
iterations: 310000,
hash: "SHA-256"
},
key,
256
);
TweetNaCl.js не содержит этих алгоритмов, но экосистема libsodium.js предоставляет:
| Метод | Скорость | Безопасность паролей | Устойчивость к GPU |
|---|---|---|---|
| SHA-512 (TweetNaCl.js) | Очень высокая | Низкая | Низкая |
| PBKDF2 | Средняя | Средняя | Средняя |
| scrypt | Низкая | Высокая | Высокая |
| Argon2 | Низкая | Очень высокая | Очень высокая |
Использование универсального хеша как системы хранения паролей:
const digest = nacl.hash(password);
Проблема заключается в том, что атакующий получает:
Даже добавление соли не решает проблему полностью:
nacl.hash(salt + password)
Безопасная схема включает:
Пример структуры записи:
{
salt: "...",
iterations: 310000,
hash: "..."
}
TweetNaCl.js может использоваться корректно в следующих частях системы:
Но не в слое:
Использование SHA-512 для паролей часто возникает из-за:
nacl.hash;Однако криптографическая корректность не равна устойчивости к перебору.