[Децентрализованные сети, Solidity] Self-Sovereign Identity + smart-contracts, дешево и сердито

Автор Сообщение
news_bot ®

Стаж: 6 лет 7 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
28-Июн-2021 11:31

Смарт-контракты и идентификация пользователейПростота и доступность этого паттерна позволяет использовать для фвторизации пользователей почти любой блокчейн, даже самый простой, так как абсолютно любой блокчейн использует приватные и публичные ключи для идентификации своих пользователей. Но при использовании полноценных смарт-контрактов, эта схема может быть доработана до любого уровня сложности и иметь любые административные функции, присущие централизованным identity системам. Поэтому в статье я буду описывать Ethereum, как наиболее развитый блокчейн с поддержкой смарт-контрактов и всеми важными механизмами обеспечения безопасности сети, так как с ним сравнивают все новые решения, а алгоритмы, используемые в этой сети давно отвечают за миллиарды долларов криптоактивов пользователей и давно доказали свою состоятельность. Поехали...Идентификация пользователейВ любых децентрализованных сетях идентифицировать пользователя или сетевой узел можно с помощью электронной подписи. Пользователь или узел (будем называть их просто “участниками”) создает ключевую пару - секретный и публичный ключи, а затем информация, созданная на основе публичного ключа, позволяет  в дальнейшем идентифицировать участника. Например, в блокчейнах Ethereum адрес (можете называть его “аккаунтом”) - это 160bit от хеша публичного ключа, т.е. чтобы создать свой адрес в Ethereum нужно:
  • создать private_key/public_key keypair для использования со схемой ECDSA (в Ethereum сейчас используется эллиптическая кривая secp256k1)
  • взять последние 160 бит от хеша публичного ключа, SHA-3(pubkey) (в Etheruem используется функция хеширования Keccak-256
  • полученное значение - адрес в сети Ethereum выглядит примерно так: 0xDC25EF3F5B8A186998338A2ADA83795FBA2D695E
Каждый раз, владельцу адреса нужно подтвердить его право владения этим адресом - он подписывает данные с помощью своего секретного ключа. Например, любая криптовалютная транзакция с какого-то адреса включает в себя публичный ключ и электронную подпись, которые доказывают, что эту транзакцию мог создать только тот, кто имеет доступ к секретному ключу, от которого “наследуется” публичный ключ, от которого “наследуется” адрес.Этот способ “подтвердить владение информацией, наследуемой от секретного ключа” крайне распространен. Например - выдача и проверка сертификатов HTTPS - это та же самая схема, сертификат HTTPS - это подписанный хеш публичного ключа с дополнительными данными (именем домена, датой истечения). Также, близкой процедурой является работа с “квалифицированной ЭЦП”, в которой контролирующий орган регистрирует публичный ключ организации вместе с информацией о ее названии, ИНН и т.п., а организация, отправляющая отчетность в электронном виде в дальнейшем подписывает ее с помощью своего секретного ключа. Блокчейн, как identity-системаУчитывая вышеописанное, публичный блокчейн, который для пользователя может быть представлен как облачный сервис, хранящий адреса и сопутствующую им информацию, является прекрасным образцом системы, которая может хранить информацию, идентифицирующую пользователей. Аутентификация всех пользователей в этой схеме проводится по приватному ключу, а публичные ключи (точнее их хеши) - хранятся “в блокчейне”. Схема эта привлекательна тем, что именно хеши публичных ключей являются “истинными” адресами в блокчейне и абсолютно любое действие в блокчейне, любая валидная транзакция является доказательством владения определенным адресом (определенным публичным ключом). При этом все важные свойства блокчейнов, такие как устойчивость к атакам, невозможность ограничения доступа, полное отсутствие секретной информации делают его идеально подходящим видом систем для хранения информации, необходимой для идентификации пользователей. Блокчейн доступен отовсюду, получить доказательство существования адреса и любые подтверждения его валидности можно с любой блокчейн-ноды, в любой точке мира, заблокировать все блокчейн-ноды в мире не представляется возможным, а изменение информации о ключах невозможно провести незаметно, оно публично проверяемо.Поэтому любые алгоритмы, требующие “доказательства владения адресом” отлично ложатся на смарт-контракты, а адрес становится уникальным иентификатором (uid) пользователя, не требующим хранения хешей паролей и иных видов shared secrets. Также, доступность и проверяемость такой “базы uid” позволяет сервису обойтись без backup-ов security информации, и в случае сбоев легко перестроить базу аккаунтов.  Для публичных блокчейнов сервер, отдающий проверяемую информацию можно запустить где угодно без всяких регистраций, без необходимости иметь криптовалюту - она просто будет получать обновления от других нод по p2p сети.Чтобы продемонстрировать удобство этой схемы опишем один из вариантов построения авторизации на сайте с использованием публичной блокчейн-сети Ethereum. Эта схема широко используется и требует от пользователя простейших действий в один клик, схожих с “login with Google”, но без отправки каких либо данных куда либо кроме сайта.РегистрацияРегистрация в этой системе - это помещение в блокчейн информации, связывающей публичный адрес в блокчейне с идентификатором и любыми доп. данными. Если совсем просто, то “в блокчейне” создается запись в key-value БД, где:
key: адрес пользоватея (f.e. 0x13668Ecf257cC15c381b461B9fEDaB5D451c8F7F)
value: {login: “vasya”, age: 18, … }
В самом минимальном варианте достаточно просто наличия адреса в контракте. Вот пример кода такого мини-контракта, который "регистрирует" любого обратившегося:
contract Users {
  mapping (address => bool) users;            // storage of user addresses
  event UserRegistered(address indexed user); // event, fired each time user is registered
  constructor() {
    register();      // register creator of contract as first user
  }
  function register() public {
    users[msg.sender] = true; 
    emit UserRegistered(msg.sender);
  }
}
Теперь, у любой ноды блокчейна можно получить эту информацию, запросив у смарт-контракта, хранящего адреса зарегистрированных пользователей данные по ключу (f.e. 0x13668Ecf257cC15c381b461B9fEDaB5D451c8F7F). Внутри данных, привязанных к адресу пользователя можно предусмотреть любую внешнюю логику - подтверждение KYC со специального адреса, принадлежащего внешнему KYC-провайдеру, указание nickname, под которым пользователь будет работать на сайте и т.п. Хранить в БЧ много данных дорого и бессмыссленно, обычно экономится каждый байт, поэтому в этом месте имеет смысл хранить только необходимый минимум. В нашем варианте это просто bool, но обычно используют struct с нужными onchain данными, например bitmask роли пользователя.Чтобы зарегистрировать адрес в смарт-контракте, пользователь самостоятельно вызывает фукнцию register() со своего адреса. Именно здесь кроется главная проблема таких систем на текущий момент - чтобы зарегистрироваться, пользователю придется оплатить транзакцию в нативной криптовалюте Ethereum - ETH, и, хотя здесь немного данных и комиссия невелика, она все равно ненулевая. Поэтому onboarding пользователей в блокчейн проектах - это отдельная боль.Но, есть и хорошее - во-первых, пользователя не удастся взломать, получив доступ к сайту - в блокчейнах каждый сам отвечает за свою безопасность. Во-вторых - регистрационные действия происходят крайне редко, и один раз заплатив, пользователь может пользоваться этой учетной записью сколько хочет, информация о ней не пропадет и отвечает за нее он сам, а не ваш проект. Это и есть Self-Sovereign Identity.  P.S. вообще, в мире блокчейна не принято считать пользователя пользователем, пока он не сделал хотя бы одно значимое действие, поэтому можно вообще не использовать контракт, а просто проверить в блокчейне, есть ли у этого адреса на балансе нужная криптовалюта ( например, токен вашего проекта)АвторизацияДля прохождения авторизации на сайте:
  • пользователь предъявляет свой адрес, под которым хочет авторизоваться
  • сайт убеждается в блокчейне, что этот адрес “зарегистрирован”
  • сайт предлагает пользователю подписать одноразовую строку (challenge)
  • пользователь подписывает challenge, предоставляя сайту ЭЦП
  • сайт проверяет подпись, и, если она верна - выдает пользователю обычный авторизационный JWT токен
Пользователи, использующие Ethereum в обязательном порядке используют ПО, которое подписывает транзакции, поэтому, если пользователь регистрировался ранее, или пользовался Ethereum в браузере, то он умеет подписывать данные своим секретным ключом. Например, при помощи расширения браузера Metamask это можно делать в один клик, одним и тем же способом отправляя криптовалюту, и точно так же подписывая challenge. При вызове функций JS библиотеки web3, которые предлагают подписать challenge, у пользователя всплывает уведомление расширения Metamask, предлагающее подписать строку. Выглядит в браузере это примерно так:

Строка, которую нужно подписать предоставляется бэкендом, который временно запоминает ее, чтобы исключить replay атаки, если атакующий перехватит подписанное сообщение и попробует его перепослать. Далее, challenge вместе с подписью отправляется на backend, который, проверив подпись удаляет одноразовый challenge и выдает пользователю авторизационный JWT токен. Дальше все работет как обычно. Примерный Кусок кода, реализующий такую схему в Django приведен ниже (это обычный view, использующий POST запрос):
Код крайне простой, и, что важно, в базе проекта нет никакой security critical информации, кроме временных challenge - никаких хешированных и соленых паролей. Даже в случае утечки SQL базы c backend нет угрозы атаки на identity пользователей. Если угонят аккаунт - то у самого пользователя, а не через ваш сайт.Такую аутентификацию можно проводить используя совершенно разные блокчейны, контракты, разные типы подписей, с помощью разного ПО, выполняющего подпись (хотя софт удобней и защищенней криптовалютных кошельков вам придется поискать).Нужен ли блокчейн?Внимательный читатель в схеме выше заметил, что в этой схеме, собственно блокчейн-то и не нужен, достаточно возможности подписать приватным ключом данные на стороне клиента. Это действительно так - и авторизация по приватному ключу сейчас активно развивается, пруф тут: https://www.w3.org/TR/webauthn-2/, так что скоро мы увидим эти схемы в наших браузерах без всяких блокчейнов. Эта схема крайне удобна тем, что сервису теперь не нужно отвечать за учетные записи пользователей, реализовывать схемы восстановления паролей, ведь каждый из этих механизмов несет в себе риски безопасности. Гораздо проще позволить пользователям самим заботиться о безопасности своих ключей - те, кто хотят мощной защиты заведут аппаратные ключи, внешние signer-ы (типа Parity Signer), а для тех, кто хранит пароли в текстовом файле на рабочем столе ничего не изменится. Помяните мое слово - фразу "Sign Up" и "Забыл пароль" лет через пять вы увидите лишь на бородатых сайтах, тоскующих по Web 2.0.Если всё таки нужен блокчейнНо, вернемся к блокчейнам. Публичный блокчейн и смарт-контракты для данной схемы - это крайне удобное неубиваемое облако для security-critical информации и реализации более сложных схем. Например, вашему сервису требуется, чтобы identity пользователя подтвердил какой-нибудь внешний KYC-провайдер, или в сети был бы всегда доступный master public key для распространения обновлений софта (актуально для IoT). В этом случае смарт-контракт несложно дополняется административными аккаунтами с различными ролями, которые могут устанавливать адресам пользователей различные признаки, типа “прошёл KYC”, “вакцинирован от COVID”. Эти действия в правильных системах защищены мультиподписями, чтобы взлом одного из аккаунтов был бы недостаточен для атаки на систему. А использование смарт-контрактов означает, что доступ к такому “API” возможен откуда угодно без всяких авторизаций и лишних действий - вся защита обеспечивается за счет все той атворизации по приватному ключу. Identity-cистема на базе смарт-контрактов не требует почти никакой работы по обеспечению безопасности хранения данных, защита инфраструктуры в ней тривиальна, и с архитектурной точки зрения системы на базе смарт-контрактов не сложнее традиционных, а намного проще, а значит, надежней.Такой функционал, разумеется, не бесплатен, и, реализуя такую систему необходимо всегда помнить про то, что в правильных блокчейнах не бывает бесплатных транзакций, а значит, любые важные административные действия в identity системе будут платными. Также, специфика кода смарт-контрактов исключает наличие в них функций, работающих сразу с большим числом сущностей, все функции должны отрабатывать за O(1), любые циклы должны быть ограничены сверху, а объем хранимых данных - минимален.Синхронизация с блокчейномВышеупомянутые моменты сильно затрудняют решение задач типа “показать список пользователей, которые ожидают подтверждения identity” или “вывести все аккаунты с nickname, начинающимся со строки vasya...”. Поэтому любые, более менее сложные блокчейн-проекты, обязательно имеют backend, задачей которого является хранение и отображение данных, получить которые из напрямую из блокчейн-ноды нельзя. Это могут быть поисковые индексы по сущностям в блокчейне, какие-то большие offchain данные, которые сами не хранятся в блокчейне, а в контрактах представлены лишь их криптографические хеши, различные агрегированные данные.Для организации такого backend-а и его синхронизации с блокчейном разумно использовать отдельный сервис синхронизации, который умеет накатывтаь обновления данных из блокчейна на свою SQL базу, параллельно проводя агрегацию и строя необходимые индексы. Такой сервис обычно использует subscription модель, подписываясь на события интересующих его контрактов. Каждый раз, когда в хранилище контракта происходит обновление (появляется новый зарегистрированный адрес, изменяются данные некоторого аккаунта) сервис видит эти изменения и изменяет свою БД в соответствии с ними.В Ethereum, Substrate и многих других блокчейнах важной частью контрактов являются Events (event UserRegistered в примере приведенном выше). Очень часто нет необходимости постоянно держать на ноде информацию о произошедших событиях, ведь ее всегда можно “перепроиграть”, просматривая блоки один за другим, и наполнить базу на backend-е информацией из событий, экономя память и ресурсы ноды и не платя за занимаемое место в state database. В вышеприведенном примере сервису синхронизации достаточно подписаться на события контракта, и, каждый раз, когда встретится событие UserRegistered обновить список адресов пользователей в сервисе. События надежно с точностью до бита фиксируются в блокчейне и не могут быть изменены позже, поэтому им можно доверять. Также, генерация события стоит в разы дешевле, чем запись значений в state database, и, технически, вышеприведенный пример можно было бы сделать вообще без хранилища, просто фиксируя каждую регистрацию с помощью событий.Крайне важным фактором для определения того, какие события считать зафиксированными в блокчейне является финализация блоков. Для Ethereum 1.0, работающего на базе консенсуса proof-of-work, “надежными” событиями считаются те, которые произошли несколько блоков назад, т.е. имеют очень низкую вероятность того, что цепочка будет заменена на другую, более сложную, и “победит” другая история транзакций. Т.е. здесь "финальность" - условная, вероятностная, хотя и довольно надежная. В сетях с другими консенсусами следует крайне внимательно относиться к тому, что для данной сети является признаком финальности транзакции. В блокчейнах с консенсусами proof-of-stake и proof-of-authority атаки типа “double spend” могут быть проведены без использования огромных мощностей, или, перестроение цепочки может быть вызвано разделением сети. В большинстве современных блокчейнов, использующих proof-of-stake и proof-of-authority используется детерминированная финальность, которая позволяет со 100% вероятностью утверждать, что финализированный блок никогда не будет откачен. Это очень удобно для сервиса синхронизации, и, пускай финализация обычно немного отстает от производства блоков (блок производит один компьютер, а финализируют его - несколько), зато, получив финализированный блок можно быть уверенным в том, что он не будет откачен (только в случае крайне серьезных сбоев в логике работы блокчейн-нод). Увы, я не могу кратко написать этот абзац, это тема отдельных статей и докладов, просто запомните - если у вас не майнинг и блок не финализирован - значит информация еще "не в блокчейне", хотя уже включена в блок и блок опубликован.Заметки на поляхПо моему скромному мнению, identity протоколы в связке с публичными блокчейнами в итоге повлияют на IT-инфраструктуру сильнее чем криптовалюты. Перенос security critical операций в блокчейн и управление публичными ключами имеют огромное значение. Эти операции мы видим в электронном документообороте, в доступе IoT устройств к облакам производителей, в выдаче verified credentials, вообще в любой области, где существуют цифровое право владения некой информацией. Публичные блокчейны позволяют избавиться от необходимости поддерживать различные виды API, контролировать доступ к серверам, убирая необходимость решать эти проблемы, точно так же как электромобили избавлены от проблем с зажиганием, подачей топлива и воздуха - их дизайн избавлен от этих инженерных проблем.Хранение identity в смарт-контрактах - это крайне простой и надежный способ организации Public Key Infrastructure для проектов, именно поэтому я решил написать статью именно об этом несложном паттерне. В следующих статьях мы поговорим о других широко используемых алгоритмах в смарт-контрактах.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_detsentralizovannye_seti (Децентрализованные сети), #_solidity, #_selfsovereign_identity, #_smartcontracts, #_detsentralizovannye_seti (
Децентрализованные сети
)
, #_solidity
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Сен 04:18
Часовой пояс: UTC + 5