На сек­цион­ном сто­ле OMEMO — откры­тый про­токол на базе алго­рит­мов из мес­сен­дже­ра Signal. OMEMO под­держи­вает отправ­ку офлай­новых сооб­щений и сек­ретные груп­повые чаты. Про­читав статью, ты узна­ешь, как работа­ет его шиф­рование изнутри и как выг­лядит переда­ча дан­ных на уров­не XMPP. И почему OMEMO — луч­шее ору­жие для защиты тво­их сек­ретов.
 

Что такое OMEMO

OMEMO рекур­сивно рас­шифро­выва­ется как OMEMO Multi-End Message and Object Encryption. Про­токол был раз­работан в 2015 году. А в 2016 году была пред­став­лена его экспе­римен­таль­ная спе­цифи­кация XEP-0384. OMEMO заин­тересо­вал меня еще тог­да, но нор­маль­ная его под­дер­жка у кли­ентов появи­лась срав­нитель­но недав­но.

Я поп­робовал мно­жес­тво кли­ентов из офи­циаль­ного спис­ка. Каж­дый отдель­но опи­сывать я здесь не буду, ска­жу лишь, что в Linux нор­маль­но работал Dino IM и отвра­титель­но работал Profanity. В Windows выбора осо­бо нет — либо Gajim, либо веб‑вер­сии дру­гих кли­ентов. На «маке» я ни один не тес­тировал за отсутс­тви­ем собс­твен­но «мака». Одна­ко Gajim работа­ет на всех плат­формах, и у него ока­зал­ся самый при­ятный интерфейс. В час­тнос­ти, есть механи­ка «сле­пого доверия», при которой тебе не надо вруч­ную регис­три­ровать фин­гер­принт собесед­ника.

 

Почему не OTR?

Про­токол Off-the-Record Messaging (OTR) дол­гое вре­мя был стан­дартом шиф­рования в Jabber. OMEMO выгод­но отли­чает­ся тем, что пре­дос­тавля­ет воз­можность отправ­ки офлайн‑сооб­щений (то есть тех, что при­дут поль­зовате­лю, ког­да он появит­ся в сети) и под­держи­вает шиф­рован­ные груп­повые чаты. Так­же он поз­воля­ет одновре­мен­но исполь­зовать нес­коль­ко устрой­ств с одним акка­унтом и на всех рас­шифро­вывать отправ­ленные тебе сооб­щения!

Как и в OTR, в OMEMO необ­ходимо вруч­ную авто­ризо­вать фин­гер­принт собесед­ника, что­бы избе­жать MITM. Луч­ше все­го про­верять его через сто­рон­ние при­ложе­ния. В отли­чие от OTR, OMEMO не пре­дос­тавля­ет прав­доподоб­ного отри­цания — все сооб­щения крип­тогра­фичес­ки под­писаны, что гаран­тиру­ет про­вер­ку их авторс­тва.

Од­нако OTR — про­токол откро­вен­но ста­рый. Шиф­рование перепи­сок сто­ит поперек гор­ла у мно­гих, и чем боль­ше прош­ло вре­мени, тем боль­ше веро­ятность того, что про­токол кем‑то ском­про­мети­рован. Кем‑то, кто уме­ет годами об этом никому не рас­ска­зывать и толь­ко тихонь­ко читать «зашиф­рован­ные» сооб­щения. Я не пред­лагаю отка­зывать­ся от PGP или OTR. Но, как мне кажет­ся, так же как и пароли, про­токо­лы сто­ит вре­мя от вре­мени менять.

 

Разбор протокола

Ос­новной документ, опи­сыва­ющий про­токол, — это XEP-0384. Но за тех­ничес­кими деталя­ми он отсы­лает к спе­цифи­каци­ям X3DH и Double Ratchet на сай­те Signal. Фак­тичес­ки OMEMO — это импле­мен­тация про­токо­ла Signal поверх про­токо­ла XMPP. OMEMO активно исполь­зует рас­ширение PubSub для пуб­ликации откры­той час­ти сво­их клю­чей на сер­вере Jabber и для зап­роса клю­чей собесед­ника, даже ког­да он находит­ся вне сети.

 

Публикация ключей

Сра­зу пос­ле вхо­да в сеть кли­ент Jabber пуб­лику­ет спи­сок сво­их устрой­ств.

<iq xmlns="jabber:client" type="set" id="effde33f-f129-4904-a418-2f114903fb8c">
<pubsub xmlns="http://jabber.org/protocol/pubsub">
<publish node="eu.siacs.conversations.axolotl.devicelist">
<item id="current">
<list xmlns="eu.siacs.conversations.axolotl">
<device id="839508582" />
</list>
</item>
</publish>
<publish-options>
<x xmlns="jabber:x:data" type="submit">
<field var="FORM_TYPE" type="hidden">
<value>http://jabber.org/protocol/pubsub#publish-options</value>
</field>
<field var="pubsub#persist_items">
<value>true</value>
</field>
<field var="pubsub#access_model">
<value>open</value>
</field>
</x>
</publish-options>
</pubsub>
</iq>

Про­токол исполь­зует имя axolotl — это ста­рое наз­вание алго­рит­ма Double Ratchet. Кли­ент сооб­щает, что у него есть одно устрой­ство с номером 839508582. Каж­дый кли­ент Jabber счи­тает­ся отдель­ным «устрой­ством», даже если они запуще­ны в одной сис­теме. Номер устрой­ства генери­рует­ся на сто­роне кли­ента как слу­чай­ное чис­ло UInt32.

<iq xmlns="jabber:client" type="set" id="dd3eabcb-2dd6-4e30-9a71-e82dcbff5846">
<pubsub xmlns="http://jabber.org/protocol/pubsub">
<publish node="eu.siacs.conversations.axolotl.bundles:839508582">
<item id="current">
<bundle xmlns="eu.siacs.conversations.axolotl">
<signedPreKeyPublic signedPreKeyId="1000768793">BS7b3OBON2Rrb9dNgiTnVtqj1RWPbKeXYkOHCrTwEXh3</signedPreKeyPublic>
<signedPreKeySignature>PbekCtW80zwFdkXfxY16x51wyMiv15XI2jp8UxTWSQJ/KxJ9siqxihRymThvwfX0UE/n2HBTe3KBX6LFIkz0BA==</signedPreKeySignature>
<identityKey>BSqKZLn8CEltZPLZtHJMWXpTgahV+BbArttWE0OIaqwK</identityKey>
<prekeys>
<preKeyPublic preKeyId="1">BfCa28WEYBKyKfVQ5tOc0Ml0AYkbkwhrcirZbX1+bb4n</preKeyPublic>
<!-- (...) 98 ключей -->
<preKeyPublic preKeyId="100">BcVt7CO5PuU5wGkMWDMoHZLbzDuqlo8DghHehZ5Nmm4j</preKeyPublic>
</prekeys>
</bundle>
</item>
</publish>
<publish-options>
<x xmlns="jabber:x:data" type="submit">
<field var="FORM_TYPE" type="hidden">
<value>http://jabber.org/protocol/pubsub#publish-options</value>
</field>
<field var="pubsub#persist_items">
<value>true</value>
</field>
<field var="pubsub#access_model">
<value>open</value>
</field>
</x>
</publish-options>
</pubsub>
</iq>

Даль­ше кли­ент пуб­лику­ет акту­аль­ный Bundle — спе­циаль­ную струк­туру с набором откры­тых клю­чей. Они нуж­ны для стар­та сес­сии OMEMO. Обра­ти вни­мание, Bundle ука­зыва­ет на номер кон­крет­ного устрой­ства 839508582. Таким обра­зом, для каж­дого устрой­ства на сер­вере хра­нит­ся уни­каль­ный набор клю­чей. Разуме­ется, это толь­ко пуб­личные час­ти клю­чей, зак­рытая часть оста­ется у кли­ента.

Клю­чи делят­ся на три типа: дол­гоживу­щий, сред­несроч­ный и одно­разо­вый.

identityKey

Дол­гоживу­щий пуб­личный ключ Curve25519. Одновре­мен­но выс­тупа­ет уни­каль­ным иден­тифика­тором каж­дого устрой­ства. Из него фор­миру­ется fingerprint — отпе­чаток устрой­ства, доверие к которо­му уста­нав­лива­ется вруч­ную.

Спе­цифи­кация про­сит соз­давать fingerprint как хеш SHA-256 от пуб­лично­го клю­ча identityKey. Одна­ко фак­тичес­кая реали­зация кли­ента ведет себя ина­че!

identityKey B2E2A1FE74930C82C60BF72F61EEB2C5DD070CD06769DC7676CB6F63AF27AA11
fingerprint 05B2E2A1FE74930C82C6D8F72F61EEB2C5DD07DCD06769DC7676CB6F63AF27AA

Срав­нив ключ с отпе­чат­ком, видим, что это тот же ключ, но в дру­гом виде. При экспор­те клю­ча он сох­раня­ется в спе­циаль­ном фор­мате с пре­фик­сом 0x05. В исходни­ках Gajim эта кон­стан­та называ­ется DJB_TYPE. То есть пре­фикс ука­зыва­ет на тип клю­ча. DJB рас­шифро­выва­ется как Daniel J. Bernstein. Это человек, впер­вые опи­сав­ший крип­тогра­фичес­кую кри­вую Curve25519. Ско­рее все­го, такой фор­мат клю­чей выб­ран для сов­мести­мос­ти с про­токо­лом Signal.

signedPreKeyPublic

Ключ для начала сес­сии. Стан­дарт тре­бует обновлять его при­мер­но раз в неделю. Обра­ти вни­мание: у клю­ча есть уни­каль­ный номер 1000768793.

signedPreKeySignature

Под­пись клю­ча signedPreKeyPublic через алго­ритм XEdDSA. Под­писыва­ется зак­рытой частью клю­ча identityKey.

prekeys

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

 

Получение ключей собеседника

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии