Обновить

pear-crypt: клиентское шифрование

pear-crypt — небольшая TypeScript-библиотека, которая шифрует на клиенте и больше ничего не делает. На входе — пароль, PIN или Recovery Code, на выходе — ciphertext, который можно положить хоть в S3, хоть в Postgres. Пароль в этот blob не зашит.

Лицензия MIT. Из зависимостей только hash-wasm: нативного Argon2id в браузере нет. AES-256-GCM и HKDF-SHA256 берутся из Web Crypto, без велосипедостроения.

Почему бы не собирать самому?

Типичный сценарий: сгенерить мастер-ключ, обернуть его паролем, тем же ключом зашифровать файл и отдельно мету. Если каждый раз клеить это из crypto.subtle, через год уже не вспомнить, был ли AAD, какой длины nonce и куда делась salt.

Здесь wire-format зашит в спеке и в тестовых векторах. Поменять раскладку байтов «чуть-чуть» нельзя: старый ciphertext просто перестанет открываться.

Под капотом

Мастер-ключ — 32 случайных байта. В открытом виде наружу не светится: только внутри AES-GCM-обёртки. Ключ обёртки получается из секрета через Argon2id: 32 МиБ памяти, два прохода, без раскладки на несколько ядер. Параметры KDF лежат в JSON рядом с nonce и ciphertext, чтобы было видно, чем именно заворачивали.

Дальше HKDF с пустой солью режет мастер-ключ на домены. В info зашито, для чего ключ: файл или метаданные. Строка вида pear-keep-file:{uid} — это и есть domain separation. Файл и его имя одним ключом не вскрываются: это разные info.

Сам файл — кадр версия | nonce 12 байт | ciphertext и GCM-тег. AAD pear-keep-file:{uid}:{bindAt} привязывает blob к идентификатору и поколению содержимого. Подменили uid или bindAt — тег не сойдётся, расшифровки не будет.

Метаданные — тот же кадр, другой ключ и JSON внутри: подпись, комментарий, время, etc. Recovery Code — 25 символов из алфавита без сомнительных похожих, группами по пять. Им заворачивается тот же мастер-ключ, но отдельно от пароля: пароль забыл — ищи бумажку с кодом.

Как проверяется, что байты не разъехались

В репозитории лежат docs/crypto/SPEC.md и JSON с векторами. Тесты бьют не только в прямую «зашифровал и тут же расшифровал», но и в зафиксированный ciphertext. Покрытие держится выше 90%. Поменяли src/ — пересобрали векторы через npm run export:vectors и закоммитили вместе с кодом. Иначе спецификация и реализация тихо разъедутся.

Чего в комплекте нет

Библиотека не решает, куда класть ciphertext, как устроен логин и когда блокировать сессию. Длину PIN тоже не проверяет. И кофе не варит.

Ошибки — PearKeepCryptoError с машинным кодом: wrongPassword, cannotDecryptMetadata и дальше по списку. Человеческого текста ошибок нет и не будет. Как и i18n.

Итого

Обернуть мастер-ключ, зашифровать контент и мету и не таскать раскладку байтов в голове — вот и весь контракт. Спека, векторы и код смотрят в одну сторону: сдвинули кадр, тесты покраснеют раньше, чем это заметит пользователь. Куда класть готовый ciphertext и как пускать человека внутрь — уже забота приложения.

Теги:
+5
Комментарии0

«Сбер» представил SberJDK — собственную промышленную Java-платформу на базе OpenJDK

«Сбер» представил корпоративный проект SberJDK — собственную промышленную Java‑платформу на базе OpenJDK. Базовая версия решения содержится в Едином реестре отечественного ПО и доступно как Open Source — без лицензионной платы за использование, в том числе в корпоративных системах, сообщили в компании.

«Сбер» представил SberJDK — собственную промышленную Java-платформу на базе OpenJDK

Публикации