panda's tech note

Advent Calendar 2021:自作メッセージングプロトコル

Day 1: 要件定義

自作メッセージングプロトコルを作るにあたって(途中で変わる可能性はありますが)要件を定義します。24日で完結するプロジェクトなので厳密な要件定義ではないですが、今回実装したい機能を最初に明文化しておきたかったので1日目にこのような形でまとめます。

要件定義

まずは,インターネットで最も広く使われている自律分散メッセージングプロトコルである電子メール(SMTP, POP, IMAP)や最近の中央集権型のSlack等の各種メッセージングアプリを参考に、要件を定義していきます。非機能要件にあげるように、今回は「自律分散システム」を目指すため、電子メールを参考にする部分が多くあるかと思います。一方で、電子メールはスパムやフィッシングのような課題(送信元の詐称や送受信における認証・認可機能の不足など)があるため、それを解決できるようなプロトコル・システム設計を目指したいと考えています。

今回のプロトコル・システムの非機能要件および機能要件は(いまのところ)以下のとおりです。

非機能要件

  1. 自律分散システム
  2. 電子メールと同程度以上の規模対応性
  3. オープンなエコシステム
  4. 拡張性

機能要件

  1. IMAPのメールボックスのような永続かつポータブルなストレージ
  2. 送信者・受信者間でのメッセージの保護(エンドツーエンド暗号化・到達確認)
  3. プロバイダ非依存の識別子(ID・アドレス)によるメッセージング
  4. 人の扱うIDとそれ以外のIDの分離(人の扱わないIDからのセマンティクスの排除)
  5. 非認可ユーザに対する受信者識別子の秘匿(相互認証IDによるメッセージング)
  6. 受信者によるメッセージ送信者の検証
  7. 匿名メッセージのサポート
  8. 1対1・1対多のプライベートメッセージ
  9. 1対多・多対多のメーリングリスト・グループチャットのようなメッセージング
  10. スレッド(例えば、メールヘッダにおける In-Reply-To
  11. 同期・非同期メッセージングのサポート

各要件の概説

非機能要件についての説明は省略します。機能要件については、それぞれ以下で説明します。

1. IMAPのメールボックスのような永続かつポータブルなストレージ

機能要件1は、メッセージの保存に関する機能です。

中央集権的なメッセージングアプリでは、アカウントが削除された場合に関連するメッセージがすべて消えてしまったり、一定期間を超えたメッセージが非表示になってしまったりします。一方で、電子メールでは一度受信したメールは永続的に保存できます。例えば、POPを使った場合はローカルのメールボックスに、IMAPの場合はメールサーバに(システム側で削除するような設定が入っていない限り)保存されます。

今回作成するメッセージングプロトコルは、電子メールのように送受信したメッセージを永続的に保存するストレージ機能を必須要件とします。また,このストレージはクラウドサービスとして提供されることも想定されるため、メールボックスのようにポータブル(他のサービスプロバイダに移行可能)であることも要件とします。

2. 送信者・受信者間でのメッセージの保護(エンドツーエンド暗号化・到達確認)

機能要件2は、Facebook (Meta?) のMessengerアプリで実装されているようなエンドツーエンドでの暗号化(中間でメッセージの仲介をするサービスプロバイダも盗聴・改ざんできない暗号化)を提供することを要件とします。これにより送信者と受信者間でのメッセージを保護します。

3. プロバイダ非依存の識別子(ID・アドレス)によるメッセージング

機能要件3〜5は識別子・ID(電子メールの場合はアドレス)に関する要件です。このあたりが電子メールでスパムやフィッシングの原因であると思っているので、今回はこの識別子については試行錯誤しながら検討していきたいと考えています。

まず、機能要件3はサービスプロバイダの識別子に依存しない識別子体系によるメッセージングを実現しようというものです。ドメイン名に依存したメールアドレスを識別子として利用している電子メールでは、(自前のドメインを運用しない限り)識別子がプロバイダに依存しています。そのため、電子メールでは識別子のポータビリティがなく、サービスプロバイダを変更する場合には識別子も変更する必要があります。

今回作成するメッセージングプロトコルでは、プロバイダ非依存の識別子を採用することで、識別子のポータビリティを担保することを要件としています。

4. 人の扱うIDとそれ以外のIDの分離(人の扱わないIDからのセマンティクスの排除)

次に、機能要件4は、メッセージングプロトコルで用いる識別子(ID)からセマンティクスを極力排除することです。

電子メールでもメッセージングアプリでも、送受信者の識別子には意味を持つことのできる文字列を使用していることが多くあります。メッセージングアプリでは内部的にこのような意味を持つ文字列の識別子からUUIDのようなセマンティクスのない識別子に変換して扱っているものもあるかと思いますが、電子メールでは意味を持つ文字列の識別子(メールアドレス)によりメールサーバ間でメッセージを中継しています。機能要件5にも関係しますが、このセマンティクスを持った識別子をシステム固有の識別子として扱うために、一旦メールアドレスが漏洩するとそのメールアドレス宛にスパムメールが届くようになったり、タイポで意図しない人にメールを送信してしまう弊害があると考えています。

そのため、今回作成するメッセージングプロトコルでは、人の扱う識別子とシステム側で扱う識別子・IDを分離し、システム側で扱う識別子からはセマンティクスを排除することで、この問題を解決しようと考えています。

5. 非認可ユーザに対する受信者識別子の秘匿(相互認証IDによるメッセージング)

機能要件4でも例示したように、電子メールではメールアドレスがメッセージの送信先の識別子となるため、このメールアドレスさえ知っていれば誰でもメールを送れてしまいます。ドメイン指定受信機能のように、ホワイトリスト形式で送信元を制限することもできますが、(この場合は、DKIMやDMARC、SPFなどのドメイン認証技術で防ぐことはできますが)送信元を詐称してメールを送ることができてしまいます。

今回作成するプロトコルでは、送受信において相互認証され、正しく認可された送信元以外のユーザには、受信者の識別子を秘匿する仕組みを導入しようと考えています。

6. 受信者によるメッセージ送信者の検証

電子メールは(PGPなどを使わない限り)送信元を容易に詐称できるため、スパムやフィッシングの温床となっています。メッセージングアプリでは、中央集権的な仕組みによりメッセージ送信者の検証をしていますが、今回は自律分散システムを目指しているので、自律分散システムにおいても送信者を検証できる仕組みを導入しようと考えています。

7. 匿名メッセージのサポート

これは必要かどうか悩みましたが、匿名でのメッセージングをサポートできると応用先が広がると思い、機能要件に入れてあります。

8. 1対1・1対多のプライベートメッセージ

電子メールのような1対1、1対多のプライベートメッセージ機能です。

9. 1対多・多対多のメーリングリスト・グループチャットのようなメッセージング

メーリングリストのような1対多のメッセージ配送やグループチャットのような多対多のメッセージ機能です。

10. スレッド(例えば、メールヘッダにおける In-Reply-To

メッセージ間の関係を構造化するためのスレッドのような仕組みは必須であると思いますので、機能要件として入れてあります。

11. 同期・非同期メッセージングのサポート

電子メールは非同期なメッセージングと言えると思います。一方で、チャットツールは同期的なメッセージを実現しています。もちろん電子メールでも同期的な使い方はできますが、同期する機能がないため、例えばメーリングリストでメッセージが行き違いになったあとにトピックが分岐してしまい、フォローが大変になったなどあるかと思います。今回作成するプロトコルでは、何らかの同期の仕組みを取り入れたいと考えています。

まとめと明日の予定

今日はざっくりとした要件定義をしました。明日はこれを元にアーキテクチャ・プロトコルの設計を行う予定です。