Существование субъекта в информационном пространстве определяется его идентификаторами: номером телефона, адресом электронной почты, аккаунтами в социальных сетях. Лишиться любого из них – значит выпасть из социального графа и потерять важные деловые контакты. Хотя социальные связи по своей природе децентрализованы, в реальности наши идентификаторы, а значит и идентичность, в значительной мере привязаны к централизованным провайдерам. В статье отмечены преимущества и недостатки такого положения дел, а так же показано, как при помощи технологии децентрализованных идентификаторов (Decentralized Identifiers, DID) строится независимая идентификация.

Централизованные провайдеры идентификации

Любой цифровой идентификатор субъекта выполняет две основные функции – позволяет отличать субъектов друг от друга и предоставляет способ связи с ними. Существующие идентификаторы чаще всего выполняют свои функции при помощи некоторого централизованного органа – провайдера идентификации. Централизованный провайдер обеспечивает уникальность идентификатора, а также самостоятельно устанавливает соответствие между идентификатором и его субъектом. Самым старым и наглядным примером централизованного провайдера идентификации является государство. Почти все государства в мире уже более 100 лет занимаются выдачей идентификаторов, в первую очередь паспортов, своим гражданам. Другой классический пример – банк. Идентификатором в данном случае выступает банковская карта или номер счета. Оператор сотовой связи присваивает идентификатор в виде телефонного номера. Сервисы электронной почты, социальные сети и мессенджеры тоже являются примерами провайдеров идентификации.

Несомненным преимуществом централизованного подхода является простота реализации и понимания.  В случае утраты сим-карты всегда можно обратиться к оператору связи с паспортом и попросить изготовить новую на тот же номер. При потере пароля от социальной сети есть шанс восстановить его, обратившись в службу поддержки. Отметим, что к реальной личности привязываются только государство и банки, проводя дорогостоящую и утомительную процедуру KYC (Знай своего клиента, англ. know your customer). Остальные провайдеры обычно определяют субъекта по факту знания им логина и пароля.

За долгое время использования централизованной идентификации накопился ряд недостатков. Начнем с невозможности сменить поставщика услуг. Например, если вы когда-то завели почтовый ящик в Gmail, то в дальнейшем перенести его на Яндекс или Mail.ru не получится. В лучшем случае вы сможете перенести историю переписки. Но письма, отправленные на вашу почту в домене gmail.com по-прежнему будут попадать на сервера компании Google. Вам придется вручную оповещать всех своих контактов о смене адреса. Впрочем, если ваш адрес публичный, и этот вариант не сработает. Конечно, можно настроить переадресацию писем на стороне Gmail, но полностью избавиться от  старого провайдера таким образом тоже не выйдет.

Другой похожий пример – это так называемое мобильное рабство, т.е. невозможность сменить оператора мобильной связи без смены номера телефона. Несмотря на принятый на эту тему закон, на данный момент в России номер можно сохранить только при смене оператора в пределах одного региона. При переезде в другой регион, или тем более в другую страну, все равно придется заводить новый номер и оповещать об этом всех своих контактов. Эти примеры наглядно демонстрируют, что фактически централизованные идентификаторы не принадлежат своим субъектам.

Вторая угроза, чаще всего исходящая от социальных сетей, это возможность блокировки со стороны провайдера. Причин может быть множество, от нарушения правил площадки или попадания в санкционные списки до простой личной неприязни или недобросовестной конкуренции. Блокировка может создать значительные неудобства для частных лиц, т.к. нарушаются социальные связи. Для публичных людей или организаций риски гораздо выше. Блокировка аккаунта в популярной социальной сети для многих из них – настоящая трагедия, несущая репутационные и финансовые потери. Примеров блокировок популярных аккаунтов огромное количество. Иногда это принимает уж слишком вопиющие формы, что заставляет каждого задуматься о способах снижения зависимости от централизованных провайдеров.

Централизованная площадка имеет полный доступ к данным субъекта и возможность управления ими без его ведома. А значит, доступ есть и у недобросовестных сотрудников указанных организаций. Так как чаще всего это крупные корпорации, счет сотрудников там идет на тысячи, за всеми уследить невозможно. Поэтому мошенничество с подделкой сим-карты, к сожалению, повседневная реальность. Не добавляют доверия и постоянные массовые утечки персональных данных клиентов.

Даже если у вас нет проблем с доверием к централизованным сервисам, нужно признать, что любой такой провайдер идентификации предоставляет лишь некий ограниченный функционал. Например, сотовая связь или электронная почта не предоставляют никаких средств шифрования или проверки подлинности отправителя. Забавный стикер из Telegram нельзя отправить пользователю WhatsApp. Конечно, мы привыкли как-то с этим жить в частных переписках, т.к. они не особо требовательны к функционалу. Но для более сложного B2C или B2B взаимодействия ограниченность существующих платформ порой оказывается непреодолимым препятствием. Выставляя товар на торговой площадке, продавец обязан соблюдать все ее правила и мириться с ограничениями. В противном случае он может лишится большинства своих клиентов. Конечно, это не всегда плохо. Чаще всего платформы дают удобство, безопасность и доверие, которого так не хватает в цифровой среде. Но никакая централизованная платформа не может предусмотреть все многообразие возможных бизнес взаимодействий. Едва ли способствует развитию в этой области и чрезмерная монополизация рынка платформ.

Наконец, сбои в работе социальных сетей и платформ – не такое уж редкое явление. Во время таких инцидентов, которые могут длится несколько часов, пользователи остаются без связи друг с другом, а бизнес - без потенциальных клиентов.

Централизованная идентификация. Идентификатор хранится в базе данных, которая управляется сторонней организацией. Значит идентификатор управляется не только субъектом, но и данной организацией.
Централизованная идентификация. Идентификатор хранится в базе данных, которая управляется сторонней организацией. Значит идентификатор управляется не только субъектом, но и данной организацией.

До недавнего времени такое положение дел оставалось привычным. Ведь даже наше собственное имя определяется паспортом, который выдан государством. С другой стороны, в реальном мире есть примеры идентификации без центральных органов. Например наши школьные клички, позывные, псевдонимы, различные обиходные названия объектов и явлений.

Для ответа на указанные выше проблемы и вызовы, и учитывая всеобщий тренд на децентрализацию, на базе консорциума W3C была создана рабочая группа под названием Decentralized Identifier Working Group, основным результатом которой стала рекомендация Decentralized Identifiers (DIDs) v1.0. В ней описан подход к созданию и управлению централизованной идентификацией субъектов, не зависящий ни от каких централизованных организаций.

Децентрализованный идентификатор – DID

Ниже представлен пример децентрализованного идентификатора (англ. Decentralized Identifiers, DID)

did:iota:6x1Xu21MBV6zQpwe9bWkrR9QdnFuYn6d3rtBXg5sBGxn

На первый взгляд он конечно выглядит не очень дружелюбно. Номер мобильного телефона можно продиктовать собеседнику, адрес электронной почты – переписать. Что же делать с этой непонятной строкой и почему она выглядит так устрашающе?

DID представляет собой обычную текстовую строку, состоящую из цифр, букв латинского алфавита и других знаков. Каждый идентификатор DID удовлетворяет стандарту URI и состоит из трех обязательных частей:

  1. Каждый DID начинается с did, что указывает, что данный URI является именно DID.

  2. iota указывает на метод DID. В данном случае используется сеть IOTA. Что такое метод DID будет разъяснено ниже.

  3. 6x1…BGxn – собственно идентификатор, вычисляемый на основе публичного ключа.

Технически процесс создания DID очень прост. На устройстве пользователя (это может быть смартфон, персональный компьютер, сервер) генерируется пара публичного и приватного ключей. Затем на основе публичного ключа тем или иным образом генерируется DID, а приватный ключ сохраняется у субъекта. Чтобы доказать факт владения DID, субъекту достаточно подписать сообщение ассоциированным с ним приватный ключом.

Практически бесконечное число возможных комбинаций DID гарантирует, что любой созданный локально DID будет глобально уникальным. Таким образом, отпадает потребность в централизованном регистраторе, который отвечает за уникальность.

Конечно, за это приходится платить тем, что DID плохо читаем человеком, его трудно продиктовать или переписать вручную. Тут мы приходим к трилемме, известной как Треугольник Зуко. Она отвеждает, из трех свойств идентификаторов (понятные человеку, защищенные, децентрализованные), одновременно могут выполняться только два свойства.

Впрочем, это не критично. Можно представить DID в виде QR кода, или просто скопировать. Тем более, что обычно этот идентификатор будет использовать соответствующий софт, не требуя от субъекта погружаться в технические подробности. Если же все-таки необходимо иметь человекочитаемый идентификатор, можно воспользоваться децентрализованными сервисами, вроде Ethereum Name Service. Конечно, за красивое имя придется заплатить, т.к. такой сервис реализуется в виде смарт контракта, исполнение которого обычно требует оплаты. Кроме того, желающих получить красивый идентификатор может быть много, что создает конкуренцию.  Тем не менее, зависимости от централизованных сервисов удасться избежать.

Как определяется, что именно я владею тем или иным DID?

В централизованных провайдерах для этого обычно служат логины и пароли, либо же физические носители, такие как сим-карты или банковские карты. Факт владения DID определяется наличием у субъекта приватного ключа, с помощью которого он был сгенерирован. Приватный ключ может храниться на смартфоне, в доверенном облачном хранилище, на специальном физическом носителе вроде Ledger.

Любой субъект может генерировать сколько угодно DID. Вы генерируете его сами. Это похоже на ЭЦП, только вы сгенерировали ее сами без удостоверяющего центра.

Кто может быть субъектом DID?

В данной статье DID рассматривается в первую очередь для идентификации людей и организаций. В принципе, это необязательно – DID можно присвоить домашнему животному, устройству интернета вещей, интернет сайту. В общем всему, у чего в реальной или виртуальной жизни может быть название. Ваш питомец вряд ли захочет запоминать 12 значную сид фразу или ходить с Ledger на ошейнике. По этому стандарт разделяет субъекта, которого идентифицирует DID, и контроллера – лицо, которое непосредственно хранит приватные ключи от DID. Контроллеров у одного DID, вообще говоря, может быть несколько.

DID Document

Идентификатор обычно позволяет не только отличить одного субъекта от другого, но и подразумевают некоторый способ связи, взаимодействия со своим субъектом и получения информации о нем. Мы можем позвонить, зная номер телефона, написать письмо, зная адрес, или отправить деньги, зная номер счета. Из странички в социальной сети можно узнать место работы или учебы человека. Давайте рассмотрим, как этот функционал реализуется в рамках технологии DID.

Итак, мы сгенерировали DID и передали его своим друзьям, коллегам и т. д. Возникает вопрос: как его использовать для связи с нами? Для этого с каждым DID ассоциирован т.н. DID Document (DIDDoc). DIDDoc представляет собой документ в формате JSON-LD. Пример DIDDoc показан ниже

{
  // указываем на принадлежность стандарту
  "@context": "https://www.w3.org/ns/did/v1",
  // собственно DID
  "id": "did:iota:6x1Xu21MBV6zQpwe9bWkrR9QdnFuYn6d3rtBXg5sBGxn",
  // информация об основном ключе, который использовался при генерации DID,
  // далее используется для доказательства владения данным DID и внесения
  // изменений в DIDDoc
  "capabilityInvocation": [
    {
      "id": "did:iota:6x1Xu21MBV6zQpwe9bWkrR9QdnFuYn6d3rtBXg5sBGxn#sign-0",
      "controller": "did:iota:6x1Xu21MBV6zQpwe9bWkrR9QdnFuYn6d3rtBXg5sBGxn",
      "type": "Ed25519VerificationKey2018",
      "publicKeyMultibase": "z9F1bQkzzat4S1g9o69tTALMWMmo33dTUhFxAMd3MPpc9"
    }
  ],
  // дополнительные ключи, ассоциированные с данным DID
  "verificationMethod": [
    {
      "id": "did:iota:6x1Xu21MBV6zQpwe9bWkrR9QdnFuYn6d3rtBXg5sBGxn#newKey",
      "controller": "did:iota:6x1Xu21MBV6zQpwe9bWkrR9QdnFuYn6d3rtBXg5sBGxn",
      "type": "Ed25519VerificationKey2018",
      "publicKeyMultibase": "zDiUBrhFgMZixEQmU1biebQiNybwfFYHyy1WyPEcY5apg"
    }
  ],
  // способы связи с субъектом
  "service": [
    {
      "id": "did:iota:6x1Xu21MBV6zQpwe9bWkrR9QdnFuYn6d3rtBXg5sBGxn#myWebsite",
      "type": "LinkedDomains",
      // в данном случае с субъектом предлагается связаться через его аккаунт на habr.com
      "serviceEndpoint": "https://habr.com/ru/users/mikelytaev/"
    }
  ]
}

Из примера видно, что DIDComm предназначен в первую очередь для хранения ассоциированных публичных ключей и способов связи с субъектом. Более подробно формат DIDDoc описан в соответствующей спецификации.

Инфраструктура публичных ключей

Децентрализованная идентификация. Субъект управляет своим DID при помощи асимметричных ключей, которые могут храниться в смартфоне, облаке, специальном устройстве или записаны на бумаге в виде сид фразы. С одним DIDDoc может быть ассоциировано несколько ключей.
Децентрализованная идентификация. Субъект управляет своим DID при помощи асимметричных ключей, которые могут храниться в смартфоне, облаке, специальном устройстве или записаны на бумаге в виде сид фразы. С одним DIDDoc может быть ассоциировано несколько ключей.

DID можно использовать в ряде различных сценариев: для авторизации на сайте, для цифровой подписи документа, сообщения или объекта интеллектуальной собственности (например NFT). Для совершения каждого из указанных действий требуется подпись приватным ключем. С точки зрения безопасности и удобства не желательно, чтобы для всех операций использовался один и тот же ключ. DIDDoc позволяет определить внутри себя сколько угодно ключей, причем каждому ключу задать свою роль – в каком случае он используется. В зависимости от важности и частоты использования ключи могут храниться в защищенном сегменте мобильного устройства, в виде записанной на бумаге сид фразы, на физическом криптокошельке, таком как Ledger.

Кроме того, ключи рекомендуется периодически менять. Провести ротацию ключей можно просто добавив новые публичные ключи в DIDDoc и удалив старые. При этом сам идентификатор DID остается неизменным.

Информация о субъекте

Хранить персональные данные, в том числе адреса электронной почты и номера телефонов, в DIDDoc не рекомендуется. В ряде случаев это даже будет противоречить законам о персональных данных, т.к. безвозвратно стереть эти данные не всегда будет возможно. Вместо этого предлагается хранить ссылки на интернет ресурсы. 

Приведем концептуальный пример. Пользователь может сохранить свое резюме со своими контактными данными на LinkedIn, а в DIDDoc записать публичную ссылку на него. С одной стороны пользователь сможет в любой момент безвозвратно удалить свои данные оттуда. С другой стороны контактные данные пользователя остаются независимыми от централизованного ресурса – пользователь в любой момент может перенести свое резюме на Яндекс Драйв или на свой домашний сервер и заменить ссылку в DIDDoc. Если пользователь в качестве своего идентификатора использовал DID – его переход с LinkedIn на другую площадку прошел бы гладко и незаметно. Использование же в качестве идентификатора аккаунта на централизованной площадке, такой как упомянутый LinkedIn, делает пользователя заложником данного ресурса – удаление аккаунта (или потеря доступа из-за местных законов) фактически означает потерю всех контактов.

Хотя формат JSON-LD позволяет задавать весьма произвольные форматы связи, рекомендуется в первую очередь использовать специально разработанные. К таковым относится DIDComm – протокол безопасного общения поверх технологии DID.

Зачем создавать несколько идентификаторов?

Почти все сталкивались с ситуацией, когда оставляя свой номер телефона в каком-нибудь магазине, на следующий день получали массу спам звонков. При этом доказать факт утечки персональных данных практически невозможно. Некоторые пытаются выйти из положения, регистрируя несколько номеров телефонов и адресов электронной почты для разных групп контактов (семья, друзья, коллеги и т. д.). Понятно, что постоянно вручную создавать новые адреса электронной почты, и уж тем более регистрировать новые номера телефонов, неудобно, дорого и плохо решает проблему.

DID генерируется абсолютно бесплатно, моментально и локально на устройстве пользователя. Значит их можно создавать столько, сколько потребуется. Соответствующие стандарты, например Peer DID и протокол Aries RFC 0023: DID Exchange Protocol 1.0 рекомендуют создавать новый DID для каждого нового контакта. Такое отношение называют Pairwise. Это обеспечивает максимальный уровень безопасности и приватности. В частности, такой подход исключает передачу ваших контактов третьим лицам – по уникальному идентификатору сразу будет ясно, кто допустил утечку, а сам скомпрометированный DID можно просто удалить.

Публичные и приватные DID

Приватная децентрализованная идентификация. Приватный DIDDoc Алисы хранится только у Боба, и наоборот.
Приватная децентрализованная идентификация. Приватный DIDDoc Алисы хранится только у Боба, и наоборот.

Как мы отметили выше, рекомендуется создавать новый уникальный DID для каждого нового контакта. Такие DID называют приватными, и они описаны в стандарте Peer DID. Процесс безопасного обмена DID между двумя новыми контактами описан в стандарте Aries RFC 0023.

Конечно, бывает и обратная ситуация, когда мы не хотим скрывать наши контактные данные. Если субъект – предприниматель, то он скорее всего наоборот заинтересован, чтобы его контакты были доступны всем потенциальным клиентам. Авторы научных работ, популярных статей или NFT коллекций могут подписать объекты своей интеллектуальной деятельности своим публичным DID, чтобы подтвердить авторство.

Технически основное различие между публичными и приватными DID состоит в том, где хранятся ассоциированные с ними DIDDoc. Приватные DIDDoc хранятся только у второго собеседника. DIDDoc публичных DID записываются в публично доступном реестре или базе данных.

Могут быть и некоторые промежуточные сценарии, например в группа в WhatsApp. В этом случае DID каждого участника должен быть известен всем остальным участникам. Такие отношения называют n-wise, а порядок создания и управления такими отношениями описан в протоколе Aries RFC 0748.

Реестры

Выше мы увидели, что с каждым DID ассоциирован DIDDoc, а также что субъект может вносить произвольные изменения в DIDDoc. Естественным образом возникает вопрос: где же хранить DIDDoc? Тут есть несколько вариантов.

В случае приватного DID никакого внешнего хранилища DIDDoc не требуется – обе стороны просто хранят DIDDoc друг друга. Они обмениваются ими в процессе первоначального установления контакта. Затем, если одной из сторон нужно внести изменения в свой DIDDoc – он просто оповещает об этом другую сторону.

DIDDoc публичного DID нужно хранить публичном реестре, таким образом, чтобы любой мог получить к нему доступ. На эту роль неплохо подходят публичные распределенные реестры общего назначения, например Ethereum, Bitcoin или IOTA. Они обладают широкой популярностью и доверием со стороны сообщества. Добавление и внесение изменений в DIDDoc осуществляется путем добавления соответствующей транзакции, либо через смарт контракт, если сеть их поддерживает. К минусам можно отнести только необходимость платы за использование. Причем, если соответствующий сервис организован в виде смарт контракта, то платить придется не только за запись (в этом случае платит субъект), но и за чтение. Конечно такое положение дел тормозит массовое внедрение. Впрочем, есть и полностью бесплатные решения, например на базе блокчейна IOTA.

Если использование DID планируется только в рамках взаимодействия внутри некоего консорциума организаций, можно использовать корпоративные блокчейны. Например DID можно присвоить сотрудникам этих организаций для доверенного общения, либо устройствам интернета вещей.

Hyperledger Indy предлагает специализированный реестр, предназначенный для хранения и управления DID, а также SDK к нему. На его базе развернуты сети Sovrin и Indicio. Данные сети развернуты на базе консорциумов организаций. Чтение DIDDoc в них публичное, а запись возможна только через членов консорциума или за плату.

Отметим, что централизованные хранилища тоже не противоречат концепции DID. Например, есть попытка реализации на базе GitHub.

Публичная децентрализованная идентификация. Идентификатором управляет только субъект. Распределенный реестр хранит идентификатор, но не может управлять им.
Публичная децентрализованная идентификация. Идентификатором управляет только субъект. Распределенный реестр хранит идентификатор, но не может управлять им.

Как связать свой DID и сторонний интернет ресурс

Допустим, какая-нибудь прогрессивная организация решила создать свой децентрализованный идентификатор и опубликовала его публичной сети. Затем она создала некоторое коммерческое предложение, подписала его своим новым DID, и разослала его своим постоянным клиентам по электронной почте. Как клиент может удостовериться, что DID действительно принадлежит этой организации? Задача это, вообще говоря не тривиальная, и до конца не решена. Однако есть одно простое решение, которое отлично подойдет к описываемому сценарию. У любой организации есть интернет сайт, и его адрес широко известен, т. к. присутствует на всех рекламных материалах, бланках организации и т. д. Кроме того, в отличие от DID, он хорошо человекочитаем. Значит нужно криптографически связать DID и интернет адрес. Для был разработан стандарт Well Known DID Configuration. Для этого в DIDDoc нужно указать адрес требуемого ресурса, а на самом ресурсе размещается криптографическое доказательство, подписанное этим DID. Таким образом, DID и интернет ресурс ссылаются друг на друга, что доказывает, что их контролирует один и тот же субъект. Естественно, все проверки могут осуществляться в автоматическом режиме.

Метод DID

Метод DID определяет алгоритм, по которому формируется DID из публичного ключа, а также хранилище DIDDoc, порядок его записи и внесения изменений.  Обычно метод DID получает свое имя по имени распределенного реестра, в который он записывает DIDDoc. Например did:eth, did:iota, did:ion. Актуальный список существующих методов DID представлен в спецификации.

Число разработанных методов DID к настоящему моменту уже превышает сотню. Конечно такое разнообразие методов имеет свои недостатки. Не существует ни одной программной реализации, которая бы поддерживала хотя бы половину указанных методов. Понимая эту проблему, был предложен Sidetree Protocol, призванный внести некоторое единообразие в существующие методы DID.

Пример создания DID в сети IOTA

Покажем простой пример создания DID и DIDDoc на локальной машине и отправки его в публичный распределенный реестр. Будем использовать основанный на направленных ациклических графах распределенный реестр IOTA. Преимуществом сети IOTA является отсутствие даже минимальной платы за транзакцию. Это позволит легко запустить данный пример самостоятельно в реальной сети, без необходимости создавать криптовалютные кошельки и платить за исполнение смарт контракта.

Ниже приведен пример на языке Rust (полный текст примера доступен в репозитории)

async fn main() -> Result<()> {

    // Генерируем пару публичного и приватного ключа по схеме Ed25519
    let keypair: KeyPair = KeyPair::new(KeyType::Ed25519)?;

    // Создаем DID и DID Document по методу IOTA DID Method
    let mut document: IotaDocument = IotaDocument::new(&keypair)?;

    // Добавляем в DIDDoc способ связи с нами - в данном случае веб сайт
    let service: IotaService = Service::from_json_value(json!({
    "id": document.id().to_url().join("#myWebsite")?,
    "type": "LinkedDomains",
    "serviceEndpoint": "https://habr.com"
    }))?;
    document.insert_service(service);

    // Создадим еще одну пару ключей, ассоциированную с этим DID
    let new_key: KeyPair = KeyPair::new(KeyType::Ed25519)?;
    let method: IotaVerificationMethod =
        IotaVerificationMethod::new(document.id().clone(), new_key.type_(), new_key.public(), "newKey")?;
    assert!(document.insert_method(method, MethodScope::VerificationMethod).is_ok());

    // Подписываем наш DIDDoc приватным ключом
    document.sign_self(keypair.private(), document.default_signing_method()?.id().clone())?;

    // Так выглядит наш DIDDoc
    println!("DID Document JSON > {:#}", document.core_document());

    // Создаем экземпляр клиента для отправки в сеть IOTA
    let client: Client = Client::new().await?;

    // Публикуем DIDDoc в сети IOTA
    client.publish_document(&document).await?;

    // Наш только что созданный и опубликованный DIDDoc можно увидеть в обозревателе сети IOTA
    let explorer: &ExplorerUrl = ExplorerUrl::mainnet();
    println!("Explore the DID Document > {}", explorer.resolver_url(document.id())?);

    Ok(())
}

Позбравляем, мы только что создали свой собственный публичный DID! Убедиться в этом можно, найдя его в обозревателе сети IOTA, например DIDDoc из данной статьи доступен по ссылке.

Заключение

Одной из основных задач остается массовое внедрение данной технологии. Концептуальные примеры использования можно найти например в документах рабочей группы DID или в книге Self-Sovereign Identity.

Как и большинство блокчейн концепций, децентрализованная идентификация в настоящее время находится в стадии активной разработки. Постоянно появляется новые протоколы, программные решения, проекты и консорциумы. Тем не менее, основные принципы, изложенные в данной статье, вряд ли претерпят значительные изменения.

Комментарии (13)