Wardhold

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

Здесь нечего принимать на веру

Ниже конкретные решения и то, чем проверяется каждое: формат хранения зафиксирован тестовыми векторами, поведение API — контрактными тестами против спецификации, инварианты данных — триггерами в PostgreSQL. В конце — отдельный блок о том, чего мы не утверждаем.

Хранение значений

Конвертное шифрование

Каждое поле шифруется собственным рабочим ключом на AES-256-GCM, а рабочий ключ — мастер-ключом инстанса. Ротация мастер-ключа перешифровывает только ключи, а не терабайты содержимого.

Контекст обязателен

В аутентификацию входит тройка «секрет, версия, ключ». Валидный шифротекст одной записи нельзя подставить вместо другой: расшифровка просто не пройдёт. Пустой контекст отвергается на уровне криптопримитива.

Свой вектор на каждое поле

Блоб самодостаточен: версия формата, вектор инициализации и тег лежат внутри. Общий вектор на запись — классический путь к повторному использованию nonce в GCM; форматом он исключён.

Формат зафиксирован векторами

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

Токены не хранятся

В базе только хеш: утечка дампа не даёт рабочих токенов. Показывается токен ровно один раз — в момент создания.

Пароли пользователей

Argon2id, отдельно от секретов. Пароль входа не годится для сейфа принципиально: он доходит до сервера, поэтому у сейфа отдельный мастер-пароль.

Доступ и наблюдаемость

Иммутабельность на уровне базы

Запрет на изменение содержимого версии и границы тенанта закрыты триггерами PostgreSQL. Ошибка в приложении не сможет переписать историю.

Имена не перебираются

Отсутствующий секрет и секрет без выданных прав отвечают одинаково — по ответу нельзя составить каталог чужих имён.

Лимиты запросов

Настраиваемые лимиты защищают от перебора и от фан-аута десятков потребителей; неудачные попытки аутентификации считаются отдельно от успешных запросов.

Журнал с отказами

Записывается и выдача, и отказ. Для расследования важнее второе: попытка прочитать чужое видна сразу.

Подпись доставки

Вебхуки подписываются Ed25519 ключом инстанса; назначение подписи входит в подписываемые байты, поэтому подпись одного типа сообщения нельзя предъявить как подпись другого.

Обновления и зависимости

Только стандартная криптография Go, без самописных примитивов и CGO. Линтер и сканер уязвимостей проходят на каждом изменении кода.

Что мы не утверждаем

Независимый криптографический аудит ещё не проводился — он в плане до того, как сейф паролей начнёт продвигаться как отдельный продукт. Сертификаций и аттестаций у продукта нет; если они нужны вашему контуру, напишите — обсудим сроки и формат.