Medium の DFINITY 公式の記事 Verifying the Internet Identity Code: A Walkthrough (2021/6/6) の日本語訳です。
Internet Identity ブロックチェーン認証システムが実行していると言い張っているコードが、確かに実行されていることを確認するためのステップバイステップガイドです。
By Joachim Breitner, Senior Researcher & Engineer | DFINITY
Internet Computer では、NNS のフロントエンドアプリや OpenChat など、さまざまな dapp にログインする際に、Internet Identity 暗号認証システムを利用できます。その際、ユーザーは自分の認証情報をきちんと管理してくれるこのサービスを信頼しています。しかし、Internet Identity が本当に自分を追跡していないことを直接確認したいと思うかもしれません。
Internet Identity は、実行していると言い張っているコードを本当に実行しているのでしょうか?この質問に答えるために、これを検証する手順を説明します。
(以下は、もちろん他のキャニスターにも適用されますが、今回は Internet Identity で話を進めます)。
動作確認
Internet Computer 上のスマートコントラクト、すなわちキャニスタースマートコントラクトは、WebAssembly のモジュールです。Internet Computer は意図的に、どのキャニスターの Wasm コードもダウンロードできないようにしています。これは、一部の開発者がコードを非公開にしたい場合があるからです。しかし、Wasm モジュールのハッシュは公開されています。これを取得する最も簡単な方法は、以下の dfx を使用することです。
$ dfx canister --no-wallet --network ic info rdmx6-jaaaa-aaaaa-aaadq-caiController: r7inp-6aaaa-aaaaa-aaabq-caiModule hash: 0xd4af9277f3e8d26fd8cdc7874a9f47b6456587fbb2a64d61b6b6880d144d3c04
ここでの「コントローラ」は、ガバナンスキャニスターのキャニスターIDです。これは、Internet Identity が Network Nervous System(NNS)によって制御され、そのコードは投票された提案によってのみ変更できるということです。これは良いことです。もしコントローラが単に、例えば私であれば、私は Internet Identity のコードを変更し、すべてのあなた達の ID を奪うことができてしまいます。
「Module hash」は、デプロイされた .wasm の SHA-256 ハッシュです。では、そのトレースを追ってみましょう。
適切なコミットメントを見つける
Internet Identity のアップグレードは NNS への提案によって行われるため、 https://github.com/ic-association/nns-proposals リポジトリの proposals/network_canister_management ディレクトリに、そのような提案の記述があるはずです。
Github の最近の NNS 提案のリスト
Internet Identity をアップグレードした最新の提案を探さなければなりません。このフォルダには残念ながら多くのキャニスターの提案が含まれており、ファイルの命名もとても役に立つというわけでもありません。私は通常、リストを下から順に見ていき、ファイルを作成または変更した最新のコミットのタイトルを含む2番目の列を見ます。
この場合、最後から2番目のものが気になります。
https://github.com/ic-association/nns-proposals/blob/main/proposals/network_canister_management/20210527T2203Z.md。このファイルには根拠と変更点の概要が書かれており、最も重要なこととして、bd51eab がアップグレードの対象となるコミットであることが書かれています。
また、このファイルによると、wasm のハッシュは d4a...c04
で、これは上で見たものと一致します。これは良いことです。Internet Identity をアップグレードする最も最近の提案を本当に見つけ、その提案が実際に通過したようです。
警告:もしあなたが疑心暗鬼であるならば、このファイルを信用しないでください。提案者があるリビジョンを指すファイルを作成し、実際には別のコードを提案に含めることを妨げるものは何もありません。だからこそ、次のステップで検証する必要があります。
ソースの取得
リビジョンがわかったので、以下でソースを取得してリビジョン bd51eab
をチェックアウトできます。
/tmp $ git clone https://github.com/dfinity/internet-identity
Klone nach 'internet-identity' ...
remote: Enumerating objects: 3959, done.
remote: Counting objects: 100% (344/344), done.
remote: Compressing objects: 100% (248/248), done.
remote: Total 3959 (delta 161), reused 207 (delta 92), pack-reused 3615
Empfange Objekte: 100% (3959/3959), 6.05 MiB | 3.94 MiB/s, Fertig.
Löse Unterschiede auf: 100% (2290/2290), Fertig.
/tmp $ cd internet-identity/
/tmp/internet-identity $ git checkout bd51eab
/tmp/internet-identity $ git log --oneline -n 1
bd51eab (HEAD, tag: mainnet-20210527T2203Z) Registers the seed phrase before showing it (#301)
最後の行では、Internet Identity チームが、提案の記述ファイル名を含むタグ名で、そのリビジョンにタグ付けしたことがわかります。とても整ってますね!
ビルドの再現
README.mdには、以下のビルド手順が記載されています。
ハッシュも表示されるので、実際には最初のコマンドを実行するだけで十分です(Docker キャニスターから .wasm をコピーする必要はありません)。
/tmp/internet-identity $ docker build -t internet-identity-service .
…
Step 26/26 : RUN sha256sum internet_identity.wasm
---> Running in 1a04644b544c
d4af9277f3e8d26fd8cdc7874a9f47b6456587fbb2a64d61b6b6880d144d3c04 internet_identity.wasm
Removing intermediate container 1a04644b544c
---> bfe6a63a7980
Successfully built bfe6a63a7980
Successfully tagged internet-identity-service:latest
成功!ハッシュが一致しました。
信じられない?自分で試してみてください(もし違うハッシュが出たら教えてください — ハッキングされたのかもしれない) Docker 用に十分な RAM がない場合、失敗することがあります。8GB あれば十分です。
この時点で、目の前にあるコードから、フロントエンドのコードを含め、https://identity.ic0.app で実行されている Internet Identity への信頼できる道筋があり、ソースコードの監査を開始できます。
キャニスター ID はどうですか?
注意深く見ていれば、キャニスター rdmx6-jaaaa-aaadq-cai のモジュールを手に入れたのに、https://identity.ic0.app のWebアプリケーションにアクセスしていることにお気づきかもしれません。では、この接続はどこにあるのでしょうか?
将来的には、Internet Computer に DNS のような「素敵なホスト名レジストリ」ができて、素敵な名前からキャニスター ID へのマッピングが保存され、セキュアな方法で(例:保証された変数を使用)「rdmx6-jaaaa-aaa-aadq-caiを提供するキャニスターはどれか」を問い合わせることができるようになると期待しています。しかし、まだそのようなことはなく、Internet Identity に素敵な名前を使用できるようにしたいため(頭痛の種になるような、後で名前を変更する必要がないように)、現時点では このマッピングはハードコードされたものです。
ここでの関連コードは、あらゆる *.ic0.app URL にアクセスする際にブラウザがダウンロードする「認証サービスワーカー」です。このコード片は、そのドメインへのすべてのリクエストをインターセプトし、クエリーコールへマップし、認証された変数を使用してレスポンスを検証します。そして実際に、マッピングはそのコードの中にあります。
const hostnameCanisterIdMap: Record<string, [string, string]> = {
'identity.ic0.app': ['rdmx6-jaaaa-aaaaa-aaadq-cai', 'ic0.app'],
'nns.ic0.app': ['qoctq-giaaa-aaaaa-aaaea-cai', 'ic0.app'],
'dscvr.ic0.app': ['h5aet-waaaa-aaaab-qaamq-cai', 'ic0.page'],
};
他のキャニスターはどうですか?
原理的には、OpenChat や NNS のキャニスターなど、他のキャニスターでも同じアプローチで動作します。しかし、キャニスターの開発者ごとに独自の方法があるため、詳細は異なるでしょう。
- キャニスターの場所とソースの改訂を伝える
- キャニスターのビルド
特に、キャニスターのビルド方法に再現性がないと、これは失敗するでしょう。そのため、https://reproducible-builds.org/ のようなプロジェクトが一般的に重要なのです。
この記事について議論したい場合は、DFINITY フォーラムに参加し、https://forum.dfinity.org/t/verifying-the-code-of-the-internet-identity-service-a-walk-through/4650 にコメントすることをご検討ください。
____