Перейти к основному содержимому
Версия: 7.0

Криптографические алгоритмы

Пассворк использует разные криптографические алгоритмы на сервере и клиенте.

Обзор используемых алгоритмов

НазначениеАлгоритмГде используется
Вывод ключа из пароляPBKDF2Получение мастер-ключа
Симметричное шифрование (сервер)AES-256-CFBСерверное шифрование БД
Симметричное шифрование (клиент)CryptoJS AES-256-CBCВсе клиентские данные
Асимметричное шифрованиеRSA-OAEPОбмен ключами
ХешированиеSHA-256, SHA-512Проверка паролей, целостность
Генерация случайных чиселWebCrypto APIГенерация ключей, IV, соли

PBKDF2 (Password-Based Key Derivation Function 2)

PBKDF2 используется для получения криптографического ключа из мастер-пароля пользователя.

Параметры на клиенте

ПараметрЗначение
АлгоритмPBKDF2
Хеш-функцияSHA-256
Итерации300 000
Длина выходного ключа512 бит
Соль20 символов, уникальная для пользователя
Библиотекаpbkdf2 (npm)

Параметры на сервере

ПараметрЗначение
АлгоритмPBKDF2
Хеш-функцияSHA-512
Итерации600 000
Длина выходного ключа512 бит
БиблиотекаPHP hash_pbkdf2()
Различие параметров

На клиенте используется SHA-256 с 300 000 итераций для баланса между безопасностью и производительностью в браузере. На сервере применяются более строгие параметры (SHA-512, 600 000 итераций) для хеширования паролей аутентификации.

Соль

ПараметрЗначение
Длина20 символов
АлфавитA-Z, a-z, 0-9, @, ! (64 символа)
Энтропия~120 бит
ГенерацияНа сервере, криптографически безопасная
ХранениеНа сервере, в профиле пользователя
УникальностьУникальная для каждого пользователя
Генерация на сервере

Соль всегда генерируется на сервере и передаётся клиенту. Клиент не генерирует соль самостоятельно, что гарантирует использование криптографически безопасного генератора.

Формат результата

Результат PBKDF2 на клиенте кодируется в строку формата:

pbkdf:sha256:300000:64:{salt}

Назначение высокого числа итераций

Большое количество итераций (300 000+) значительно замедляет атаки перебором:

  • Одна попытка подбора занимает существенное время
  • Параллельный перебор на GPU затруднён
  • Использование предвычисленных таблиц невозможно из-за уникальной соли

Автоматическая миграция хешей

Система поддерживает автоматическую миграцию хешей PBKDF2 при изменении параметров.

Формат хеша на сервере:

pbkdf:{base64_hash}:{algorithm}:{iterations}:{length}:{salt}

Пример: pbkdf:Abc123...==:sha512:600000:64:xY3zKmN9qR2w...

Механизм миграции:

  1. Пользователь входит в систему
  2. Система проверяет параметры существующего хеша
  3. Если параметры отличаются от текущих настроек → требуется перехеширование
  4. Пароль автоматически хешируется с новыми параметрами
  5. Новый хеш сохраняется в базу данных

Что можно обновлять:

ПараметрТекущее значениеПримеры новых значений
Алгоритм хешированияSHA-512SHA3-512, BLAKE2b512
Количество итераций600 0001 000 000, 2 000 000
Длина ключа512 бит256, 1024 бит
Постепенная миграция

При обновлении параметров:

  • Новые пользователи → сразу получают хеши с новыми параметрами
  • Существующие пользователи → миграция происходит при следующем входе
  • Пользователи без входа → старые хеши продолжают работать

Миграция происходит прозрачно для пользователя — он просто вводит пароль как обычно.


AES (Advanced Encryption Standard)

Пассворк использует разные режимы AES на сервере и клиенте.

Серверное шифрование: AES-256-CFB

На сервере используется AES-256 в режиме CFB (Cipher Feedback) через OpenSSL.

ПараметрЗначение
АлгоритмAES-256-CFB
Длина ключа256 бит
Размер блока128 бит
Вектор инициализации (IV)128 бит, случайный
БиблиотекаOpenSSL (через PHP)

Особенности режима CFB:

  • Потоковый режим шифрования
  • Не требует дополнения (padding)
  • IV хранится вместе с шифротекстом

Применение: шифрование данных в БД (внешние ссылки, настройки, LDAP/SMTP пароли).

Генерация IV на сервере:

ПараметрЗначение
Длина128 бит
ГенераторКриптографически безопасный (CSPRNG ОС)
УникальностьНовый IV для каждой операции шифрования
ХранениеВ начале зашифрованных данных

Структура зашифрованных данных: [128 бит IV][шифротекст]

Клиентское шифрование: CryptoJS AES-256-CBC

На клиенте используется библиотека CryptoJS для всех операций симметричного шифрования.

ПараметрЗначение
БиблиотекаCryptoJS
РежимCBC (Cipher Block Chaining)
Длина ключа256 бит
ДополнениеPKCS#7
IVАвтоматический (128 бит)
KDFВстроенная функция вывода ключа
Кодирование результатаBase32

Преобразование ключа в AES-256:

Симметричные ключи в Пассворке имеют длину 100 символов (~596 бит энтропии), но AES-256 требует ровно 256-битный ключ. CryptoJS автоматически выполняет преобразование через функцию вывода ключа (KDF):

  1. Генерируется случайная 64-битная соль
  2. Исходный 100-символьный ключ преобразуется в 256-битный ключ AES
  3. Соль сохраняется вместе с шифротекстом для расшифровки
Почему избыточная энтропия?

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

Генерация IV на клиенте:

CryptoJS автоматически генерирует IV при каждом шифровании:

ПараметрЗначение
Длина128 бит
Генераторwindow.crypto.getRandomValues()
УникальностьНовый IV для каждой операции шифрования
Формат храненияВключён в OpenSSL-совместимый формат

Формат вывода CryptoJS: "Salted__" + [64 бит соль] + [шифротекст с IV] → Base64

Почему разные режимы?

КритерийСервер (CFB)Клиент (CBC)
БиблиотекаOpenSSLCryptoJS
Причина выбораСтандарт PHPОбратная совместимость
ПреимуществаПотоковый режимШирокая поддержка

CryptoJS vs WebCrypto API

Для симметричного шифрования на клиенте используется библиотека CryptoJS, а не нативный WebCrypto API. Ниже представлено сравнение этих подходов.

Сравнение:

АспектCryptoJSWebCrypto API
РеализацияЧистый JavaScriptНативный код браузера
ПроизводительностьМедленнееЗначительно быстрее
Защита от timing attacksНет гарантийЗащита на уровне реализации
Управление памятьюКлючи в JS heapКлючи могут быть non-extractable
APIСинхронныйАсинхронный (Promise)
СовместимостьЛюбое JS-окружениеТолько современные браузеры

Почему используется CryptoJS:

  1. Обратная совместимость — существующие зашифрованные данные используют формат CryptoJS
  2. Синхронный API — проще интеграция в существующую кодовую базу
  3. Универсальность — работает в любом JavaScript-окружении

Меры безопасности в текущей реализации:

  • PBKDF2 через отдельную библиотеку — мастер-ключ выводится через криптографически стойкий PBKDF2
  • WebCrypto для RSA — критичные асимметричные операции выполняются через нативный API
  • Криптографически безопасная генерация IV — через crypto.getRandomValues(), а не Math.random()
  • Данные шифруются один раз — timing attacks требуют многократных операций с одним ключом

Оценка рисков:

УгрозаУровень рискаОбоснование
Timing attacksНизкийТребуют локального доступа к браузеру
Memory exposureНизкийПри наличии такого доступа проще перехватить пароль при вводе
Известные CVEМинимальныйИспользуемая версия CryptoJS не имеет критических уязвимостей
Перспективы развития

В будущих версиях планируется постепенный переход на WebCrypto API для симметричного шифрования. Это позволит:

  • Использовать AES-GCM (authenticated encryption) вместо AES-CBC
  • Повысить производительность в 10-100 раз
  • Обеспечить защиту ключей на уровне браузера

Миграция будет выполнена с сохранением обратной совместимости для существующих данных.


RSA (Rivest–Shamir–Adleman)

RSA используется для асимметричного шифрования — безопасного обмена симметричными ключами между пользователями.

Параметры

ПараметрЗначение
АлгоритмRSA-OAEP
Длина модуля2048 бит
Публичная экспонента65537 (0x010001)
Хеш-функцияSHA-256
БиблиотекаWebCrypto API (crypto.subtle)

Генерация ключей

RSA-ключи генерируются на клиенте с использованием WebCrypto API:

crypto.subtle.generateKey({
name: 'RSA-OAEP',
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: 'SHA-256'
}, true, ['encrypt', 'decrypt'])

Форматы хранения

КлючФорматОписание
ПубличныйSPKI (PEM)SubjectPublicKeyInfo
ПриватныйPKCS#8 (PEM)Зашифрован мастер-ключом

Поддержка форматов

Система поддерживает импорт ключей в форматах:

  • PKCS#1-----BEGIN RSA PRIVATE KEY-----
  • PKCS#8-----BEGIN PRIVATE KEY-----
  • SPKI-----BEGIN PUBLIC KEY-----
  • JWK — JSON Web Key (для конвертации)

Обратная совместимость

Для старых 1024-битных ключей используется fallback на библиотеку JSEncrypt, так как WebCrypto API не поддерживает RSA-1024.

Почему RSA-2048?

АспектОписание
БезопасностьЭквивалентна 112 битам симметричного шифрования
ПроизводительностьПриемлемая скорость в браузере
СовместимостьШирокая поддержка во всех браузерах

Хеширование

SHA-256

ПараметрЗначение
Длина хеша256 бит
Библиотека (клиент)js-sha256
ИспользованиеХеш мастер-ключа, PBKDF2, RSA-OAEP

SHA-512

ПараметрЗначение
Длина хеша512 бит
Библиотека (клиент)js-sha512
Библиотека (сервер)PHP hash()
ИспользованиеPBKDF2 на сервере, хеш серверного ключа, индексы поиска

Генерация случайных чисел

Все криптографические параметры генерируются с использованием криптографически стойких генераторов случайных чисел (CSPRNG).

Источники энтропии

На сервере (PHP)

ГенераторИсточник энтропииПрименение
random_bytes()CSPRNG операционной системыБинарные данные (ключи, токены)
random_int()CSPRNG операционной системыСимвольные строки (соли, коды)

Источники энтропии ОС:

  • Linux: /dev/urandom, getrandom() syscall
  • Windows: CryptGenRandom() (CryptoAPI)
  • macOS: arc4random_buf()

На клиенте (JavaScript)

ГенераторИсточник энтропииПрименение
window.crypto.getRandomValues()CSPRNG браузера/ОСЧисла, массивы
CryptoJS.lib.WordArray.random()crypto.getRandomValues()IV для AES

Источники энтропии браузера:

  • Chromium/Electron: BoringSSL CSPRNG
  • Firefox: NSS (Network Security Services)
  • Safari: CommonCrypto (Apple)

Гарантии криптографической стойкости

СвойствоГарантия
НепредсказуемостьНевозможно предсказать следующее значение
Равномерное распределениеВсе значения равновероятны
НесмещённостьИспользуется rejection sampling
ДоступностьГенераторы не блокируются

Генерируемые ключи и токены

Что генерируетсяДлинаАлфавитЭнтропия
Симметричные ключи
Ключ сейфа100 символовA-Z, a-z, 0-9, @, !~596 бит
Ключ записи100 символовA-Z, a-z, 0-9, @, !~596 бит
Ключ вложения100 символовA-Z, a-z, 0-9, @, !~596 бит
Ключ ссылки100 символов → 256 битA-Z, a-z, 0-9, @, !~596 бит вход
Ключ шифрования сервера256 битБинарный256 бит
Соли
Соль PBKDF220 символовA-Z, a-z, 0-9, @, !~120 бит
Соль сейфа32 символаA-Z, a-z, 0-9, @, !~190 бит
Токены и секреты
Secret Code (localStorage)100 символовA-Z, a-z, 0-9~596 бит
Extension Secret60 символовA-Z, a-z, 0-9~357 бит
Auth Token (расширение)400 битHex400 бит
Токен внешней ссылки43 символаA-Z, a-z, 0-9~256 бит
Session токены
Access Token256 битBase64256 бит
Refresh Token256 битBase64256 бит
Векторы инициализации
IV (сервер, AES-CFB)128 битБинарный128 бит
IV (клиент, AES-CBC)128 битБинарный128 бит

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

Для токенов, требующих гарантированной уникальности (токены ссылок, invite-коды), выполняется проверка в базе данных:

  1. Генерируется случайный токен
  2. Проверяется уникальность в БД
  3. При коллизии — генерируется заново
  4. Возвращается гарантированно уникальный токен

Вероятность коллизии:

  • 43 символа из 62: ~10^77 комбинаций
  • При миллиарде токенов: вероятность коллизии ≈ 10^-59
  • Практически невозможно

Криптографические библиотеки

На клиенте (JavaScript/TypeScript)

БиблиотекаНазначение
WebCrypto APIRSA операции, случайные числа
CryptoJSAES шифрование (все данные)
js-sha256SHA-256 хеширование
js-sha512SHA-512 хеширование
pbkdf2PBKDF2 вывод ключа
node-jsencryptRSA fallback (1024-бит)
pem-jwkКонвертация PEM ↔ JWK
totp-generatorГенерация TOTP кодов

На сервере (PHP)

КомпонентНазначение
OpenSSLAES-256-CFB шифрование
hash()SHA-256, SHA-512 хеширование
hash_pbkdf2()PBKDF2 вывод ключа
random_bytes()Генерация случайных данных

Сравнение с отраслевыми стандартами

ПараметрПассворкNIST рекомендации (2024)Статус
Симметричное шифрованиеAES-256AES-128/192/256
Асимметричное шифрованиеRSA-2048RSA-2048+
ХешированиеSHA-256/512SHA-2 family
PBKDF2 итерации300K/600K≥310K (SHA-256)
Генератор случайных чиселCSPRNGCSPRNG