これは、2連続のブログポストの1つ目です。
-
- チャットアプリ Signal に Web の未来を見た話 (この記事)
背景
最近、チャットアプリの Signal が注目されています。
発端は Elon Mask が "Use Signal" とツイートしたことらしいですが、 Jack Dorsey や Edward Snowden なども以前から推奨しています。
Signal は Whatsapp のファウンダーを含むメンバーによって作成されたチャットアプリですが、アプリそのもの以上にSingal protocol にその価値があります。
これは匿名性とセキュリティに主眼を置いており、他のアプリケーションには存在しない面白い特徴を有しています。
匿名性は、単にサーバー (事業者)に対して情報を隠すのみならず、情報流出の危険性がないという点で、1. ユーザーを無用なリスクに晒さず 2. 事業者側のセキュリティコストを下げてくれるという優れた特徴です。
特に、グループチャットで匿名性を保つ仕組みが興味深いので、この記事ではなぜそれが注目に値するのかを解説していきます。
実際のプロトコルに関しては次回の記事で解説予定です。
が、その前に前提知識として属性ベース証明書について解説します。
技術的な解説になるので、あまり興味がない人は読み飛ばしてください。
属性ベース証明書 (Attribute Based Credential, ABC)
ここで解説している内容のほとんどは Brands による解説に準拠しています
現在最も広く用いられている電子証明書の形式は、SSL/TLS で利用されている x.509 です。
これは、基本的に対象者の公開鍵が真正なものであることを証明するためだけに使われ、あらかじめ信頼された認証局が公開鍵 (と、メタデータ)に署名することで行われます。
その対象者の属性 (e.g. どこの国の主体なのか?年齢は?名前は?)はエンコードしないか、あるいは単なる文書としてエンコードします。
通信している Web サービスが意図したものであるかを確かめるためであるならばこれで十分なのですが、個人が認証のために使うようなシナリオでは問題が発生します。
例えば、自治体が住民に対して提供する身分証明書を電子証明書として発行し、ユーザーはその証明書を別のサービスへの認証に使うと仮定します。
この場合、公開鍵以外に属性をエンコードする必要があります。単純に考えると、電子証明書発行時に属性を確認し、署名対象となる文書内にデータを埋め込むことで達成できそうです。
ですが、これだけだと匿名性が達成できません。
住民が別のサービスに対して身分を証明したい場合、全ての情報を相手に明かす必要があります。
それを防ぐため、楕円曲線暗号を用いて以下のように情報をエンコードします。
- $Hash()$ ... 適当な暗号学的 Hash 関数
- || ... バイト列の結合
- $G$, $G_1$, $G_2$, $G_3$ ... 楕円曲線状の NUMS
- $G_1$ ... 「年齢」に対応する
- $G_2$ ... 「扶養家族の数」に対応
- $G_3$ ... 「居住地域」に対応
- $m_1$, $m_2$, $m_3$ ... エンコードしたいメッセージ
- $m_1$ には例えば 18歳ならば 18 が入る。
- $m_2$ には扶養家族が二人いる場合 2 が入る
- $m_3$ には、居住地域の通し番号が入る(通し番号と居住地域名には別途対応表が必要)
- $a$ ... ユーザーの秘密鍵
- $A$ ... 対応する公開鍵
$$ H = G_1 * m_1 + G_2 * m_2 + G_3 * m_3 + G * a $$
を計算し、この $H$ を証明書の実体とします。(これは、メッセージに対する一般化 Pedersen Commitment という呼ばれ方をします)
このように表現することで何が嬉しいのかというと、証明書を提示する際に
- $H$
- $H$ に対する認証局の署名
- $a$ および明かしたい属性を知っていることに対するゼロ知識証明
を提供することで、必要最小限の情報だけを相手に明かすことができます。($H$ を見ただけでは属性に関する情報は一切見えない点に注意)
ゼロ知識証明には、例えば一般化 Schnorr 署名が利用可能です。以下のようにして計算します。
- nonce をメッセージの数 + 1だけ作成 ($w_1$, $w_2$, $w_3$, $w_4$)
- nonce point $R := w_1 * G_1 + w_2 * G_2 + w_3 * G_3 + w_4 * G$ を計算
- Challenge $c := Hash(R || H)$ を計算
- $s_1 := c * m_1+ w_1$ とし、同様に $s_2$, $s_3$ を計算
- $s_4 := c * a + w_4$ を計算
- $(R, s_1, s_2, s_3, s_4)$ を署名とする
- 検証は公開情報である nonce point $R$ と、証明書 $H$ を用い、以下の等式が成り立つかを確認することで行う。
$$s_1 * G_1 + s_2 * G_2 + s_3 * G_3 + G * s_4 = R + cH$$
こうすると、相手に情報を一切明かすことなく 1. $H$ が認証局に承認されていること 2. $H$ を構築するのに必要な秘密の値 ($m_1$, $m_2$, $m_3$, $a$) を知っていることを証明できます。
大抵の場合は、特定の情報を明かしてからそれが証明書に含まれていることを証明したいケースがほとんどです。
例えば、自分が 18 歳であることを証明しつつ、他の情報を一切漏らしたくない場合、上記の nonce point の計算時に $m_1 * G_1$ を除外し、 「$H$ から $18 * G_1$ を引いた値」に対応する秘密の値を知っていることをゼロ知識証明します。
また、 属性同士が等しいことを (それぞれの属性を明かすことなく) 証明したり、 属性が一定の範囲にあることを証明することもできます (e.g. 扶養家族が3人以上、年齢が18歳以上、など)
このような属性ベース証明書を用いた認証手法は、ユーザーが自身の情報を管理することで情報流出のリスクを最小限に抑えることができるという特性を持ち、OpenID Connect のような現在主流の認証方式よりも優れています。
このような特性は、アメリカ政府の指針や EU の指針 にも叶うものです。
なぜ普及していないのか
属性ベース証明書が優れたものであるならば、なぜ今まで普及して来なかったのでしょうか?
色々と理由はありますが、そのうち重要なものとして、「認証基盤として用いる場合にはパブリックプロトコルとして実装されなくてはならない」という点が挙げられます。
認証局と検証者が異なる主体の場合、それぞれが好き勝手なプロトコルを使っても意味がありません。
したがって共通のプロトコルを作成する必要がありますが、これはボトムアップで行うことが難しく、行政機関(や、それに準ずるほど影響力が大きい主体)が主導する必要がありました。
MicroSoft が U-Prove というフレームワークで同様の仕組みを開発しています。これがイマイチ普及していないのもこの理由(と、セキュリティの証明が難しいこと)からだと思われます。(セキュリティの問題に関してはこちらを参照)
しかし、そのような主体にとってユーザーのプライバシーを守ることは優先度の高いミッションであるとは考えられていませんでした。直接収益を得る方法がないならばなおさらです。
近年は、ウェブサービスにおける個人情報保護の必要性が高まっており、状況は変わりつつあります。EU は特に基本的人権としての自己情報コントロール権に重きを置いており、属性ベース証明書のプロトコル作成に出資したり、指針 を策定したりといった活動を行なっています。
認証局から情報を隠す
上記のスキームは、実際のスキームを可能な限り単純化したものであり、匿名性に関して様々な改良を加えることができます。例えば
- 認証局に証明書を見せても、それが署名時とは別のものに見えるようにする。
- 署名時に認証局が属性を知らないようにする。
- 検証者に何度証明書を見せても、それらが毎回別々のものに見えるようにする。
詳細な解説は複雑なので省略しますが、特に 3 の場合、証明書自体を提示するのではなく、証明書を秘密の値でランダマイズした後に、1. その値が元は別の有効な証明書から作られていること 2. その証明書は認証条件を満たしていること 3. ランダマイズする際に使用した値を知っていること
をゼロ知識証明することで認証します。
Signal で使われる証明書も 3 の特性を持ったものであり、 multi-show unlinkable であるという言い方をします。
営利サービスとして匿名証明書を利用する
複数回提示してもそれらを紐づけることができないユースケースの場合、「署名者と検証者が同一である」ようなスキームを考えることに意味が出てきます。
なぜかというと、「サーバーが証明書という形でユーザーに何らかの権利を与え、その後にユーザーが証明書を提示して権利を行使する」という形のサービスであっても、サーバーはユーザーを紐づけることができず、したがって最大の匿名性が達成されるためです。
実際、Signal で活用されているのはこのような仕組みです。「他人が検証する必要はない」という仮定を置くことにより、計算効率を数倍から数十倍高めることができます。
特筆すべき点として、このような形式で証明書を利用する場合、最初に解説したような ID サービスとしての証明書の利用とは異なり、サービス提供者は別の主体とプロトコル互換性について協調する必要がない、つまり勝手にサービスとして公開できるという点が挙げられます。
さらに、将来的に類似の仕組みである ID サービスとしての証明書が普及した際に組み合わせることも容易にできます (「公的機関の発行する属性ベース証明書によって18歳以上であることを証明したものにのみ、このサービスのための新たな匿名証明書を発行する」というような使い方をします。)したがって、社会全体での新しい認証基盤のアダプションをサポートするものとなり得るのです。
ブロックチェーンアプリケーションに興味がある人にとっては、匿名証明書によって「トークン」が実現できる。という言い方の方が魅力的かもしれません。
実際、匿名証明書はもともと電子通貨を実現するために提案されたものでした。
BTC-backed なステーブルコインや、現実世界での物品の所有権を示すトークン、回数券、割引券など、ブロックチェーンの応用例として考えられていたものの多くは匿名証明書で実現することができ、匿名性、手数料、パフォーマンスなどの面でブロックチェーンを使うよりも利点があります。
そして、——ここが重要な点ですが—— 従来はこのような匿名サービスを提供するインセンティブがありませんでした。
長らくWebサービスをマネタイズする方法は大きく二つしか存在しなかったためです。
- ユーザーに広告を提示する
- クレジットカードや PayPal で課金する
1 の場合は、個人情報を用いて広告をパーソナライズするメリットが大きいため、匿名のまま行うことが難しいという難点があります。(一応 DuckDuckGo が匿名のまま広告を表示する試みを行なっています)
2 の場合は、クレジットカード情報と紐づけた時点で匿名性が大きく損なわれるため、匿名サービスには適していません。
しかし、現在は3つ目の方法が現実的になりつつあります。
無論、暗号通貨、特に Lightning Network (LN)による課金です。
同時に、LN による課金は、スパムリクエストを防ぐことができる という大きなメリットがあります。
一般に匿名サービスにおいては、ユーザーが大量のリクエストをしてきても、そのユーザーを ban することができないため、サーバーのリソースが逼迫することが大きな問題になります。
匿名証明書の発行や、より一般に API リクエストに対して LN で課金することで、このような問題にも対処することが可能になります。
ほとんどの web サービスは、個人情報を実際に入手する必要はない(金さえ払ってもらえれば良い)ため、 LN の普及に伴い、こういった匿名Webサービスが台頭してくるものと思われます。
このような新時代のウェブアプリケーションの先駆けとして、 Signal が注目されているというわけです。
次回は、実際に Signal がどのように匿名証明書を利用してグループチャットの匿名性を高めているのかを解説します。
まとめ
- 属性ベース証明書はユーザーに優れた匿名性とセキュリティを提供するが、導入が難しい
- 属性ベース証明書の仕組みを営利サービスに応用することで、匿名性の高いアプリケーションの構築が可能になる。
- 従来はそのようなサービスを作る利点がなかったが、暗号通貨によってビジネスとして成り立つ可能性が見込まれ始めている。
- そのようなサービスの先駆けとして Signal が注目されている。