Documentation
¶
Overview ¶
Package keywrap — обёртка приватной половины подписного ключа для хранения в базе.
Чей это ключ ¶
Ключ обёртки — уже объявленная ручка `authn.jwks-encryption-key-hex` (приёмка §2.5). Второй ручки об этом предмете не заводится: одна из двух неизбежно оказалась бы необязательной, и профиль развёртывания, задавший «не ту», выглядел бы настроенным.
Почему AES-256-GCM ¶
Форма ручки уже объявлена ровно 32 байтами, то есть размером ключа симметричного шифра. Изобретать второй размер незачем. GCM выбран потому, что даёт подлинность вместе с сокрытием: подменённая в базе строка не разворачивается, а не разворачивается в мусор, который потом окажется «ключом».
Ключей может быть НЕСКОЛЬКО, и это единственный путь смены ¶
Ключ обёртки — секрет, а у секрета обязан быть путь смены: утёк, скомпрометирован носитель, сменился владелец, истёк срок политики. Одно значение такого пути не даёт вовсе: новое значение не открывает ни одной уже записанной приватной половины, и вернуть их нечем.
Поэтому обёртка принимает ПЕРЕЧЕНЬ: ПЕРВЫЙ ключ оборачивает, ВСЕ открывают (задача #1065). Смена — это постановка нового ключа первым при сохранённом прежнем: записанного никто не трогает, простоя нет, а хранилище переходит на новый ключ само, по мере того как ключница порождает ключи и снимает старые.
Чего перечень НЕ даёт: ВЫВОДА ключа. Прежний ключ открывает написанное им до тех пор, пока в наборе есть хоть одна строка, обёрнутая им, — и утёкший ключ снимается из перечня не раньше. Переобёртывание уже записанного — отдельная работа со своим окном и своим решением о срыве на середине.
Что этот пакет НЕ делает ¶
Он не журналирует, не оборачивает ошибки текстом, содержащим материал, и не печатает ни одного байта ни на каком пути (§6.10). Текст отказа называет операцию, а не значение.
Index ¶
Constants ¶
const KeySize = 32
KeySize — размер ключа обёртки в байтах. Объявлен ЧИСЛОМ ровно здесь; страж старта конфигурации сверяется с этим числом, а не со своей копией.
Variables ¶
var ErrNotWrapped = errors.New("keywrap: value is not a wrapped key")
ErrNotWrapped — предъявленное значение обёрткой не является (слишком коротко, чтобы нести хотя бы вектор инициализации).
var ErrUnwrap = errors.New("keywrap: unwrap failed")
ErrUnwrap — обёртка не снимается: ключ не тот, значение повреждено или подменено. Причина НЕ различается намеренно — различение подсказывало бы предъявителю, какая половина неверна.
Functions ¶
This section is empty.
Types ¶
type Wrapper ¶
type Wrapper struct {
// contains filtered or unexported fields
}
Wrapper оборачивает и разворачивает приватный материал.
Ключей может быть несколько: первый делает КАЖДУЮ новую обёртку, все годятся для снятия. Разделение полей выражает это по построению — «обернуть чем-то из перечня» здесь не выражается, а не запрещено правилом.
func New ¶
New строит обёртку на ПЕРЕЧНЕ ключей объявленного размера: первый оборачивает, все открывают.
Перечень из одного ключа — законный и самый частый случай; профиль развёртывания, назвавший одно значение, не меняется оттого, что смена ключа стала возможной.
Пустой перечень — ОТКАЗ. Обёртка без ключей не открыла бы ничего, а построенная выглядела бы собранной: «не сужаем» здесь читалось бы как «запрещаем».
Ключ негодного размера — ОТКАЗ на ЛЮБОЙ позиции, а не усечение и не растяжение: «привели к нужной длине» означает, что ошибка настройки становится рабочим режимом. Отказ называет ПОЗИЦИЮ — со списком из трёх значений оператор иначе не знает, какое чинить, — и никогда значение.
func (*Wrapper) KeyCount ¶
KeyCount — сколько ключей названо.
Печатается при старте: перечень растёт с каждой сменой и не убывает сам, а «названо шесть ключей» иначе невидимо ниоткуда — то есть работу по выводу прежних ключей некому начать.
func (*Wrapper) Unwrap ¶
Unwrap снимает обёртку ЛЮБЫМ из названных ключей, в порядке объявления.
Перебор не ослабляет проверку подлинности: каждый ключ проверяет метку целостности сам, поэтому подменённое значение не открывается НИ ОДНИМ — и перечень из десяти отвергает ровно то же, что перечень из одного.
Порядок выбран не для красоты: первым стоит текущий ключ, а самый частый читатель — подписывающий ключ, только что записанный им же. Перебор поэтому оканчивается на первом ключе на горячем пути, а длина перечня оплачивается лишь на строках, доставшихся от прежних ключей.
Текст отказа не несёт ни байта материала и не называет, чем именно значение негодно и какой ключ его не открыл: у сообщения об ошибке нет адресата, которому эта разница помогала бы законно.