# ADR-030: Верхняя граница итераций KDF и проверка границ на клиенте

Уточняет [ADR-013](013-password-policy-kdf.md): нижняя граница остаётся, к ней добавляется верхняя.

## Контекст

ADR-013 задаёт целевое число итераций PBKDF2 и нижнюю границу, верхней нет. `iter` — единственное поле ключевого блоба, которое сервер разбирает сам и потом сам же раздаёт клиентам через `GET /api/kdf`, то есть отвечает за его вменяемость. Регистрация одним запросом с `iter = 10^12` принималась: аккаунт после этого нельзя ни открыть, ни удалить — обе операции начинаются с PBKDF2, который не заканчивается.

С другой стороны, клиент брал число итераций из `GET /api/kdf` и `GET /api/config` как есть и считал по нему `authKey`, который тут же уходит на сервер. Нижнюю границу не проверял никто, кроме сервера, и только у блоба — а PBKDF2 считает клиент, и проверить параметр перед вычислением может только он.

## Решение

- Границы числа итераций — от 600 000 до 10 000 000. Верхняя — порядок над целевым значением 1 000 000: запас на повышение и предел, за которым вход перестаёт заканчиваться.
- Сервер отвергает ключевой блоб с `iter` вне границ: `400 invalid`, `field: blob`.
- Клиент проверяет границы до `deriveBits`: и число из `GET /api/kdf` и `GET /api/config`, и `iter` при разборе блоба. Число от сервера вне границ — «параметры ключа не совпали»; `iter` блоба вне границ — «ключ аккаунта повреждён», как любой другой дефект его формы (ADR-028).
- Границы записаны в `docs/crypto.md` рядом с целевым значением.

## Следствия

- Аккаунт с неоткрываемым `iter` завести нельзя.
- Ослабить KDF ответом `/api/kdf` тоже нельзя: границу держат обе стороны, и клиентская стоит раньше вычисления. Активно-злонамеренный оператор остаётся вне модели угроз — он подменит и сам клиент.
- Поднять целевое значение выше верхней границы без правки границы не выйдет. Это и требуется: такое повышение — решение, а не настройка.
