🔏Мульти/Пороговые/Агрегированные подписи
Критически важные компоненты KLYNTAR
BLS12-381
Переходим к одной из важнейших концепций в KLYNTAR Cryptoland. Речь пойдёт про мульти- и пороговые подписи. Мы включили эту таблицу не просто так. На первый взгляд может показаться что это одно и тоже и как мы уже упоминали, ввиду работы с документациями других проектов, мы часто встречали что эти понятия путаются. Отдельно стоят агрегированные подписи, а точнее в целом механизм агрегации(ключей и подписей).
Поскольку в KLYNTAR как мультиподписи так и пороговые подписи построены с использованием одной кривой(вышеупомянутая BLS12-381), то прежде надо познакомится с ней.
Если вы ничего до этого не слышали об этой кривой и представленных механизмах, то не волнуйтесь - BLS так же используется в таких именитых проектах как ZCash,Algorand,Chia,Harmony,Filecoin,Dfinity(ICP) и так же планируется использование в Ethereum 2.0
BLS(Barreto-Lynn-Scott) кривая которая отлично подходит для так называемого спаривания в криптографии на основе пар. Кривая BLS12-381 была разработана Шоном Боу в начале 2017 года в качестве основы для обновления протокола Zcash. Она удобна для осуществления цифровой подписи и для создания zkSNARKS.
Метод подписи Боне-Линн-Шахама (BLS) считается надежным для генерации подписи. Он использует билинейную пару с группой эллиптических кривых и обеспечивает некоторую защиту от атак индексного исчисления. BLS также производит короткие подписи и доказал свою безопасность. В то время как подписи Шнорра требуют случайных чисел для создания нескольких подписантов, BLS не полагается на них.
Спаривание кривых
Нам понадобится очень специальная функция, которая берет две точки P и Q на кривой (или на двух разных кривых) и отображает их в число:
Мы также требуем от этой функции одно важное свойство. Если у нас есть какое-то секретное число x и две точки P и Q , мы должны получить один и тот же результат независимо от того, какую точку мы умножаем на это число:
По сути, нам нужно иметь возможность поменять местами множители точек между двумя аргументами без изменения результата. В более общем случае все эти свопы должны давать один и тот же результат:
Мультиподписи
Если Алиса хочет создать BLS подпись, она сначала генерирует приватный ключ как точку на эллиптической кривой и вычисляет публичный ключ используя публично известную базовую точку по такой формуле:
Она берет хэш сообщения, а затем сопоставляет хеш-значение с точкой на эллиптической кривой. Если мы используем SHA-256, мы можем преобразовать сообщение в 256-битную x-точку. Если нам не удается получить точку на кривой, мы добавляем инкрементное значение. Подпись сообщения вычисляется так:
Благодаря возможностям объединения пар получаем
Вот наглядно
А так выглядит проверка подписи
Агрегация
Теперь объединим все подписи в блоке! Представьте, что у нас есть 1000 валидаторов и каждый из них должен проголосовать за включения некоторого блока в блокчейн. На каждого валидатора получается подпись Si , открытый ключ Pi и сообщение M(мета данные блока-хэш, индекс и т.д.) . Зачем хранить все подписи, если их можно комбинировать? В конце концов, нас волнует только, действительны ли все подписи. Агрегированная подпись будет просто суммой всех подписей валидаторов:
Для проверки блока нам нужно проверить, что выполняется следующее равенство:
Доказательство
Пороговые подписи (TBLS)
Следующим важным компонентом в KLYNTAR являются пороговые подписи (t of n или threshold signatures). Их важность и преимущество перед мультиподписями состоит в том, что они служат конкретной цели - добиться того, что произвести транзакцию смогут T из N участников которые были установлены раннее и которые владеют частью приватного ключа группы.
Мультиподписи универсальные и могут быть полезны в разных местах. Например, их преимущество в том, что легко добиться эффективности при генерации N of N подписи - для этого нужно чтоб N членов подписали своими приватными ключами сообщение M, а после произвести агрегацию публичных ключей и подписей и получить мастер-ключ группы(условный PubN) и подпись(SigN). Благодаря свойствам агрегации не надо будет хранить в блокчейне N подписей и N публичных ключей(как это происходит в наивных реализациях мультиподписи),а вместо N подписей достаточно будет проверить только 1 агрегированную что дарит нам супер эффективность - узнаете детальней в разделе ниже.
Проблема наступает тогда, когда не все подписанты могут быть согласны с решением подписи, а достаточно только лишь достижения некоторого порога T(то бишь чтоб не менее T из N участников согласились подписать транзакцию). В этом случае, при использовании мультиподписи нам надо составлять какие-то дополнительные правила выполнения, а так же растет размер доказательства.
Приведу пример - пускай у нас есть 10 человек которые решили с помощью BLS мультиподписи сгенерировать подпись(для транзакции, стейкинга, фиксации унобтаниума или чего-то ещё). Пускай 6 из них согласны, а 4 других - против. При этом заранее вы поставили порог на свой публичный агрегированный ключ в 6/10.
Для 6 человек нет проблем подписать что-то, а затем агрегировать свои 6 публичных ключей в 48 байтовый единый BLS публичный. С подписью аналогично - всё сводиться к одной.
Однако, для доказательства сети того, что соблюдается порог в 6/10 вы должны предоставить 4 отдельных 48-байтовых адреса тех кто не согласился. Это потому, что для сети нет другого способа по другому узнать сколько из ключей входит в MasterPub1-6.Это приводит нас к сложностям ведь подписантов может быть не 10, а 200.
Было бы хорошо если б вся "магия" выполнялась вне блокчейна - ноды не будут знать о каких-то порогах, не будут раскрывать публичные ключи несогласных и так далее. Всё что должен знать блокчейн - это факт того, что был достигнут нужный порог и что вот перед нами валидная подпись.
Этого можно достичь с пороговыми подписями. В KLYNTAR мы используем реализацию TBLS с использованием вышеупомянутой кривой
Для безопасной процедуры DKG(распределённой генерации ключа) используется схема проверяемого разделения секрета Фельдмана. Она позволяет на основе схемы Бенало разделить общий приватный ключ и на основе векторов верификации сгенерировать общий публичный ключ. В таком случае, T из N участников группы смогут подписывать сообщения от имени группы.
Демонстрация
Для общего понимания хода работы давайте сгенерируем ключи и протестируем их возможности. Так же это будет что-то типа полезного пособия если у вас возникнут трудности с их использованием в Apollo. Ну или если вы мало что поняли из информации выше, то сейчас получите более наглядное объяснение
Мультиподписи
Перейдите в Cryptoland
В раскрывающемся меню выберите multisig и в разделе операций generate. Теперь сгенерируйте пару
Для теста сгенерируйте и сохраните себе несколько пар. Давайте сгенерируем 3 пары
Не забывайте сохранять свои пары. Автоматическое сохранение добавится в будущих версиях Apollo
Вот пары которые получились
Теперь эти 3 стороны могут подписать какое-то сообщение. Пусть это будет SEND 5 KLY TO BOB
У вас должны будут получится 3 подписи
Вы можете взять любую из них и соответствующий публичный ключ и проверить
А дальше начинается криптографическая магия. Агрегация. Для этого, три стороны или любое другое лицо могут взять публичные подписи и адреса и агрегировать их воедино
Агрегация публичных ключей
Агрегация подписей
Теперь вы получили пару. Давайте проверим
Думаю, теперь невероятные свойства стали более наглядными и очевидными
Пороговые подписи
В Cryptoland теперь выберите thresholdsig
Давайте смоделируем ситуацию - пусть вы с 5 другими друзьями хотите создать такой адрес, произвести какое-либо действие с которого можно будет только по соглашению 4 друзей. Имеем ситуацию 4/6. Перед вами будут такие поля
Введём наш порог 4, наш ID(пусть будет 1) и ID других друзей. В качестве ID можно выбрать что угодно, но легче пользоваться числовыми идентификаторами. Раз количество сторон 6, то и идентификаторов должно быть 6(включительно с вашим)
Вы получите такой вот большой вывод
Первым идёт вектор верификации
Это необходимый компонент для пороговых подписей который поможет убедиться сторонам(в данном случае вашим остальным 5 друзьям) что разделение секрета прошло безопасно, что та часть которую они получили - валидная и что каждая из сторон получила не больше чем нужно(то бишь всё будет безопасно и порог в 4/6 не будет нарушен)
Он публичный. Отправьте его остальным друзьям
Далее - шары
Это компонент так называемой распределённой генерации ключа(DKG).Они отправляются по одной каждому другу и не должны быть где-то опубликованы. Это гарантия в первую очередь вашей же безопасности. Шару с вашим идентификатором оставляете у себя (там где For user with id 1 так как вы ранее выбрали такой ID)
Они НЕ публичные, а отправляются тайно каждому другу
Последнее - ваш обновлённый ID
Так же сохраните его. Он необходим будет для верификации шар и генерации частичной подписи
Что дальше?
Дальше ваши 5 друзей повторяют у себя в кошельках тоже самое. Только им нужно вставить свой ID и аналогичный набор идентификаторов для всей вашей группы(тоже 1,2,3,4,5,6 как генерировал первый друг которым являетесь вы в этом примере).
Друг с ID=2
Друг с ID=3
Друг с ID=4
Друг с ID=5
Друг с ID=6
Этап 2
Вы отправляете всем друзьям полученный вектор верификации и шары каждому из друзей. В то же время, получаете и от них верификационный вектор и свою шару.
По завершению процедуры у вас как у друга с ID=1 должен быть такой набор:
5 верификационных вектора от каждого из друзей + ваш собственный (итого 6)
Ваш обновлённый ID который вы получили на первом шаге
5 шар от каждого из друзей + ваша собственная которую вы сгенерировали на первом этапе(там где For user with id 1)
Этап 3 - верификация шар
Теперь вам надо убедится что никто из ваших друзей не схитрил и не отправил ложную шару. В противном случае - вы рискуете потерять свой голос ведь нарушители смогут решить всё без вас предоставив функции валидную шару которую они сохранят у себя ранее
Для этого выберите verifyShare режим
Введите сюда ваш ID который вы получили когда генерировали шары у себя, шару полученную от какого-то друга и вектор верификации который он прислал
Для примера мы продолжаем играть роль друга с ID=1. Давайте проверим шару от друга с ID=4. Можете подняться выше и сверить вектор верификации и шару для друга с ID=1 которая получилась у друга с ID=4
Делаем проверку
Отлично, друг с ID=4 не подвёл и не обманул нас. Так же пройдитесь по остальным и сделайте аналогичную проверку
Если где-то вы увидите false - процедура может быть остановлена. Это значит что соответствующий друг пытается вас обмануть. Чтобы убедится что вы все храните шары для одинакового верификационного вектора сравните полученные векторы с другими друзьями. У всех у вас должны быть одинаковые векторы от каждого из друзей
Этап 4 - генерация группового ключа
Для всей остальной сети ваши закулисные дела скрыты. Однако, для приема платежей на адрес вам необходимо получить общий(групповой) адрес который будет идентифицировать вашу группу.
Для этого выберите опцию deriveGroupPub
Введите через символ-разделитель верификационные векторы всех участников
Не волнуйтесь, в других кошельках или модулях Apollo процедура будет проще и не будет выглядеть такой "страшной"😃
Полученный ключ и есть вашим групповым ключом - распространяйте его и получайте платежи
Этап 5 - время траты
Настало время распорядится ресурсами на адресе. По сценарию, мы установили порог 4/6. Так же согласие могут выразить и 5/6 и даже все 6 одновременно. И тем не менее, для упрощения представим что согласилось 4 друга.
Выберите режим signaShare. Это позволит сгенерировать вам частичную подпись
Вставим необходимое и сгенерируем подпись. Такую же процедуру повторяют и другие 3 друга(потому что вы четвёртый в этой компании)
Друг с ID=1
Друг с ID=2
Друг с ID=3
Друг с ID=4
Отлично, теперь вы можете опубликовать свои частичные подписи или отправить кому-то одному кто их собирает и создать подпись группы. Она будет проверяться публичным ключом группы который вы создали ранее
Для этого выберите опцию buildFullSignature
Вставьте все 4 частичные подписи и идентификаторы
Теперь имея такую подпись, сеть сможет проверить ее используя публичный ключ группы. И вы можете это сделать тоже - в интерфейсе Apollo. Для этого выберите опцию verify и вставьте необходимое
Проверка
Важность для KLYNTAR в будущем
Мультиподписи и пороговые подписи крайне важные как на начальных этапах, так и для будущих разработок. Помимо криптографической красоты которую они уже позволяют применять в KLYNTAR уже сейчас(голосования, агрегация которая дает ускорения + сводит N пруфов к единому доказательству, какие-то сторонние применения) они так же представляют огромный интерес для будущих разработок.
Приведу пару идей:
Ускоренная проверка состояния Мы в будущем планируем модифицировать систему верификации состояния до того, чтоб для блока существовало единое доказательство его валидности и валидности транзакций внутри. Этого можно добиться путём агрегации
Построение in-memory хэш таблиц с различными вариантами агрегированных публичных ключей Ввиду такой природы блокчейнов что не все валидаторы могут быть одновременно в сети, надо бы сделать более рациональное использование возможностей агрегации. Так мы можем, например, создать маппинг где ключом будет некоторый публичный ключ текущего набора валидаторов, а значением - набор отсутствующих валидаторов. Таким образом можно добиться минимизации раундов коммуникации и при этом каждый из узлов будет знать наверняка на каком из блоков какие валидаторы не подписали его(будучи оффлайн, к примеру). Так можно продолжать проверять ставки на блок используя O(1) доступность маппинга
Разные схемы что только придут в голову Это и гомоморфное сокрытие благодаря чему каким-то публичным ключом будет на самом деле тайно управлять несколько сторон, это разные гибкие возможности стейкинга, свопов, обмена Унобтаниума, заморозки ставок для сервисов и многое другое. Эх мультиподписи, спасибо что вы есть 😃
Ссылки
Last updated