Кольцевые подписи
Как доказать «я владею одним из этих ключей», не говоря каким
Кольцевая подпись доказывает, что подписант знает приватный ключ к одному из n публичных ключей кольца, не раскрывая, к какому. Monero использует линкуемую версию — к подписи прилагается key image, чтобы нельзя было потратить один выход дважды. Сегодняшняя схема называется CLSAG, размер кольца — 16.
Сначала — обычная подпись Шнорра
Чтобы понять кольцо, сначала разберём, как доказать знание одного ключа x для P = x·G:
- Подписант берёт случайное
αи вычисляетα·G. - Вычисляет «вызов»
c = Hs(сообщение ‖ α·G). - Вычисляет ответ
s = α − c·x. Подпись — это(c, s). - Проверяющий восстанавливает
s·G + c·P = (α − cx)·G + c·x·G = α·Gи проверяет, чтоHs(сообщение ‖ α·G) = c.
Без знания x подобрать s под заданный c невозможно: c зависит от α·G, которое нужно зафиксировать до того, как узнаешь c.
Идея кольца: замкнуть цепочку вызовов
Теперь у нас n публичных ключей P₀ … Pₙ₋₁, и мы знаем ключ только к одному, скажем Pπ. Трюк: каждый вызов вычисляется из предыдущего звена, и цепочка замыкается в кольцо.
- На позиции настоящего ключа π берём случайное
αи вычисляем следующий вызов:c_{π+1} = Hs(m ‖ α·G). - Для каждого следующего (чужого) ключа выбираем случайный
sᵢи считаемc_{i+1} = Hs(m ‖ sᵢ·G + cᵢ·Pᵢ). Обходим кольцо по кругу. - Возвращаемся к π, уже зная
c_π. Чтобы кольцо сошлось, нужноs_π·G + c_π·P_π = α·G, то естьs_π = α − c_π·x. Это можно вычислить только зная x. - Подпись:
(c₀, s₀, s₁, …, sₙ₋₁).
Проверяющий стартует с c₀, проходит все звенья по одной формуле и проверяет, что вернулся в тот же c₀. Все звенья выглядят одинаково — по подписи нельзя понять, где было «замыкание».
Линкуемость: LSAG
Простая кольцевая подпись не мешает потратить один и тот же выход дважды в разных кольцах. Поэтому Monero использует линкуемую подпись: подписант публикует key image I = x·Hp(P_π) и в каждом звене дополнительно доказывает, что тот же самый x связывает I и Hp(Pᵢ):
Два использования одного ключа дадут одинаковый I — и сеть отклонит вторую трату.
MLSAG → CLSAG
В RingCT нужно доказать не одно, а два утверждения на каждый член кольца: знание ключа выхода и то, что разность обязательств — обязательство к нулю (см. RingCT). Сначала (2017) это делали подписью MLSAG — по сути, два кольца, склеенные вместе: на каждого члена кольца по два s.
В октябре 2020 года (хардфорк v13) её заменили на CLSAG (Concise LSAG): два ключа на позиции сворачиваются в один через случайную линейную комбинацию с коэффициентами-хешами. На каждого члена кольца — один s. Подпись стала примерно на 25% меньше и быстрее проверяется.
История размера кольца
| Когда | Минимум участников | Комментарий |
|---|---|---|
| 2014 | 1 (без приманок) | Наследие CryptoNote: «0-mixin» транзакции разрешены |
| 2016 | 3 | Хардфорк, запрет нулевых колец |
| 2017 | 5 | Вместе с RingCT |
| апрель 2018 | 7 | После исследований цепной реакции (chain reaction) |
| октябрь 2018 | 11, фиксированно | Размер кольца стал одинаковым у всех |
| август 2022 | 16, фиксированно | Хардфорк v15 (вместе с Bulletproofs+ и view tags) |
Почему размер фиксирован? Если бы каждый выбирал сам, нестандартный размер кольца стал бы отпечатком кошелька.
Почему не 1000?
Размер CLSAG и время проверки растут линейно с размером кольца. Кольцо на 1000 участников — это ~32 КБ на каждый вход и в десятки раз более медленная синхронизация узлов. Схемы с логарифмическим размером (Triptych, Arcturus, Seraphis) исследовались, но в итоге Monero выбрал радикальный вариант — FCMP++, где «кольцо» — весь блокчейн.