WebRTC SFU Sora における E2EE の実装案

2020 年 7月版

自社製品である WebRTC SFU Sora における E2EE 対応が一通り方針が塊、現在誠意実装中です。アルファ版を今年の夏中には出せるのではないかと考えています。

どんな方針で実装しているかを書いていきます。

まとめ

  • Go で X3DH / Double Ratchet 実装は完了
  • WebAssembly で X3DH / Double Ratchet の動作済み
  • Sora と連携するメッセージ用プロトコルは実装済み
  • JavaScript と WebAssembly の連携部分は実装済み
  • SFrame は未着手、検証時は独自プロトコルで実装する

最新の Chrome で動作する

今回、E2EE は最新の Chrome で動作することを目標としました。

現在の libwebrtc では Insertable Streams API を実現するには現時点では libwebrtc 自体に手を入れる必要があり、後回しにすることにしました。

E2EE を実現するプロトコル

ベースには Signal プロトコルを採用しました。

  • 鍵合意アルゴリズムには X3DH で x25519/ed25519 を採用
  • メッセージの鍵共有アルゴリズムには Double Ratchet を採用
  • メッセージの暗号方式には AES-GCM を採用
  • メディアの暗号プロトコルには SFrame を採用

それぞれのクライアントと WebRTC SFU を経由してセッションを張るという、効率の悪い方式です。Message Layer Secruity (MLS) が安定するまではこの方式で行きます。

Signal / WhatsApp / LINE / Facebook Messenger / Google Duo はこの方式を採用しています。

IdentityKey の生成と保存

ブラウザで秘密鍵の保存はほぼ不可能と判断したので、諦めます。毎回生成することにしました。これは永続的な IdentityKey だけでなく、中期的な PreKey も同様です。

WebAssembly の採用

WebCrypto には x25519 / ed25519 が用意されていません。また、Signal プロトコルはかなり複雑な状態を持つ事もあり、状態管理と暗号処理はすべて WebAssembly 側で行うことにしました。

Go/WabAssembly の採用

Go は 1.11 で WebAssembly に対応しました。Go で書いたコードを JS 側から呼び出せるようになります。

Go を採用した理由としては、Go の暗号ライブラリは Go のみで書かれているため、WebAssembly 化が可能です。また Go は標準ライブラリとして x25519 や ed25519 のライブラリを持っています。OpenSSL や BoringSSL を利用することなく標準の暗号ライブラリを持っているのはおそらくGo くらいではないでしょうか。

暗号ライブラリの自作はやってはいけないと言われている一つです。Go の暗号ライブラリは Google で利用されているというのも信頼できます。

Base32-Crockford ライブラリの作成

Sora の Connection ID は UUIDv4 を Crockford’s Base32 でエンコードしたものを利用しています。

このライブラリは(GitHub にあった良さげなライブラリを使っていたらそもそもエンコードもデコードもバグっていたという)悲しい事件があったため、自社で開発する事にしました。

Erlang/OTP / 時雨堂 / WebRTC / E2EE

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store