Zero Knowledge SSO
この記事について Decentralized SSOはすっごく前に作った作品ですが、それにZK(Zero Knowledge Proof)を追加したプロトコルを作りました。 この記事では、そのプロコトル制作の背景やプロコトルについて書きます。 正直、プロトコルと言うほど崇高なものではないですが、便宜上そう言ってます。 Zero Knowledge SSOに行き着くまで 前まではZKの意義深さがよく分からずにスルーしていたのですが、今年(2024年)の7月にZKの重要性を理解しました。 これは回路を書いたりと手を動かしてみたことが大きいと思います。 ZKの数学は難しいのですが、有用なライブラリ多いため実際に手を動かす分には数学無しでも扱えるようになっています。 そこからアプリケーションでもっとZKが使われて欲しい!との思いから、数学なしでZKのアプリケーションを作るための記事を書いたりしていました。 さて、それが一段落したところで、ZKを使ってSSOできないかな、と思い立ちました。 というのも、以前に作っていたDecentralized SSOでの課題を解決できそうな気がしたためです。 Decentralized SSOでは複数のIdPからユーザの信頼情報を取得しますが、その際に複数のサービス間で同一のアイデンティティを利用するためアイデンティティが紐づくというプライバシー上の懸念がありました。 そこでZKを使うことで、ユーザの信頼情報のみを取得し、アイデンティティを紐付けないでSSOを実現できるのではないか、と考えました。 色々と調べていくうちに、Ethereum財団のPSE(Privacy and Scaling Explorations)がSemaphoreというアイデンティティ関連のライブラリを作っていたため、それを利用することにしました。 また、PSEがAcceleration Programというタスクにお金を払うプログラムをやっていたため、それに応募できそうだと思いました。 ということで、1週間程度で雑にプロトタイプと仕様を作り、それを提出しました。 PSEの人がレビューをした後、今ちょうどスマホの鍵管理アプリを作っているプロジェクトがあって、それと統合したらどうだろうか?と言われました。 スマホアプリで実際に実現が出来そうだったので、それに同意してそのプロジェクトが完了するのを待っている最中です(2024/10/07 現在)。 待ち続けて2ヶ月以上経つので、一旦アウトプットとして書いておきます。 なお、以下はEthResearchにも投稿した内容の日本語版です。 プロトコル 概要 Anoidenは、ゼロ知識証明を用いた匿名シングルサインオンプロトコルです。このプロトコルは、アイデンティティプロバイダー(IdP)とサービスプロバイダー(SP)が共謀しても、ユーザのアイデンティティを秘密に保ちながらIdPからの情報を使ってSPへのサインインを可能にします。これはSemaphoreライブラリを利用します。 Connect ユーザは、IdPが指定する方法(Eメールや電話番号の登録など)でアカウントを作成し、ゼロ知識証明の鍵と接続します。 Auth SPはIdPを信頼しており、認証のエンドポイントを知っています。ユーザはSPに対してIdPでのログインを要求し、ノンスを取得します。 その後、ユーザは自身のアイデンティティの証明を作成しIdPに送信します。IdPは証明を確認し、ユーザが正当であれば対応する署名を作成します。 用語 拡張機能: ブラウザ拡張機能(アプリでも可)で、ユーザの鍵管理や証明の作成等を行います。SPとIdPが結託してもアイデンティティが秘匿されるために必要です。 anoiden.js: ウェブサイトのクライアントに拡張機能と通信するためのインターフェイスを提供します。 アイデンティティプロバイダー(IdP): ユーザの正当性の情報をSPに提供する主体です。 サービスプロバイダー(SP): IdPから提供されるユーザの正当性を利用する主体です。 IdPへの登録(Connect) ユーザがIdPでアカウント登録を完了すると、そのアカウントと拡張機能側の鍵を連携できます。 この連携により、ユーザは今後、認証を要求された際にこのIdPを使用可能になります。 また、鍵を使って匿名でIdPにログインすることも可能になります。 IdPのクライアントはanoiden.jsを通じて、署名と公開鍵を取得します。 const {signature, publicKey} = await connect(serviceName, nonce); ここでserviceNameはIdPのサービス名で、鍵の管理に使用されます。 nonceは推測が不可能な文字列で、IdPのサーバサイドから取得します。 以下の図はIdPのクライアントがユーザの署名を取得するまでのフローです。 クライアントは取得した署名、公開鍵、ノンスをサーバに送信します。 サーバはセッションを確認し、そのユーザに対してそのノンスを発行したかを確認します。 有効であれば署名を検証し、identifier(公開鍵のposeidonハッシュ)を取得し、Merkle Treeにidentifierを追加し、追加後のMerkle Rootを保存します。 Authorize SPはIdPを利用する際、事前に利用することを伝えており、IdPからクライアントIDを受け取っていることとします。...