本文へスキップ
Anon Wallet

ウォレットの同期

シールドウォレットには、通常のウォレットにはない課題があります。残高は自分のアドレスに紐づけて保存されるのではなく、ほかの人のものと一緒に共有プール内に置かれた暗号化ノートの集まりです。プールには所有者のラベルがありません。自分の資産を知るには、全ノートから自分のものを探す必要があります。

方法は2つあり、その選択はシールドウォレットが行う最も重要なプライバシー上の判断です。

ノートを見つける2つの方法

サーバーに探してもらう。 ウォレットが閲覧鍵から導出したフィルターをインデクサーに送り、インデクサーが一致する記録を返します。高速で低コストですが、検索対象をすべて明かします。フィルターそのものが質問であり、サーバーは回答するために読む必要があるからです。

データをダウンロードして自分で探す。 ウォレットはプールの履歴を固定された公開の断片として取得し、各ノートの復号をローカルで試みます。復号できるのは自分のノートだけです。どのノートが自分のものかをサーバーに尋ねていないため、サーバーはそれを知りません。

Anonは後者の方法、ダイジェスト同期を使います。

クエリそのものが漏えいになる理由

ログの問題と捉え、インデクサーがクエリを保存しないと約束すれば問題がなくなると考えたくなります。しかし、そうではありません。

インデクサーへのクエリは、Xに一致するコミットメントを返してほしいという条件です。この条件は閲覧鍵から計算されます。サーバーは答えるために解析する必要があるため、保存方針にかかわらず、リクエストごとに鍵に関係する情報が他者のマシンのメモリに入ります。ログを無効にして変わるのはディスクに書き込む内容であり、サーバーが知る必要があった情報は変わりません。

ログを残さないことは約束です。データを持たないことはアーキテクチャです。

ネットワーク層の匿名性でもクエリモデルを救えないのは、このためです。Tor経由でリクエストしても、インデクサーはどのコミットメントを尋ねたかを正確に知ります。その際にIPを知らないだけです。

ダイジェストリクエストの例

Anonの履歴は、変更されない均一なチャンクのファイルとしてCDNに保存されています。リクエストは次のようになります。

GET https://digest.anon.inc/v4/1/chunks/42/commitments.json.gz

ここに個人固有の内容はありません。パスはチェーン全体の状態から決まります。チャンク42は固定されたEthereumのブロック範囲を含み、世界中の誰が取得しても同じバイト列です。資金がないウォレットも、千個のノートを持つウォレットも、同じファイルに同じリクエストを送ります。

その結果、次の2つの特性が得られます。

  • 履歴リクエストにウォレット由来のフィルターがありません。 すべてを記録し、完全に侵害されたCDNでも、あるIPが公開ファイルをダウンロードしたことしかわかりません。そのファイルのどの内容が利用者に関係するかは、CDNが持っている情報ではないためわかりません。
  • 一致したかどうかは見えません。 バイト列が届いた後、復号はデバイス上で行われます。エッジはチャンク42に自分のノートが含まれていたかを判断できません。インデクサーの場合は、フィルターが質問だったため、構造上それを知っています。

封印済みチャンクは変更されず、エッジに1年間キャッシュされます。そのため安定運用時には、近くのCloudflareデータセンターが応答し、リクエストはAnonのインフラまで到達しません。

各サーバーに見える情報

同期だけがウォレットのネットワーク活動ではなく、各経路の特性も異なります。具体的には次のとおりです。

経路 運営者 自分の鍵に由来するか わかる情報
ダイジェストCDN(digest.anon.inc) Cloudflare いいえ IPと、特定のブロック範囲の公開ファイルを取得したこと
インデクサーのヘッドAPI(api.anon.inc) Anon いいえ IPと、チェーンの先端からどの程度遅れているか
PPOIプロキシ 第三者アグリゲーターの手前にあるAnon はい IPと、問い合わせたブラインドされたコミットメント
RPCエンドポイント 設定したプロバイダー いいえ IPと、問い合わせた公開アドレスやコントラクト
ブロードキャスターネットワーク(Waku) P2P いいえ 暗号化されたトランザクションメッセージ。ピアは接続メタデータを観測できる場合がある
OHTTP経由のペイマスター Anonゲートウェイと独立した中継 いいえ 中継はクライアントIPと暗号化されたリクエストを、ゲートウェイは復号済みリクエストと送信時刻を確認できる

ヘッドAPIは、チャンクの封印と封印の間にウォレットを最新状態に保ちます。受け取るのはブロックまたはシーケンスのカーソルで、ウォレットの内容ではなくチェーン上の同期位置です。そのためわかるのは「このIPはこのあたりまで同期済み」であり、「このノートはその人のもの」ではありません。

PPOI プロキシは別のプライバシー経路です。無実証明では閲覧鍵から導いたブラインドコミットメントを集約サービスに問い合わせるため、ウォレット固有の要求になります。現在のプロキシは読み取りをキャッシュし、要求パラメーターをキャッシュのメタデータに保存できます。キャッシュキーのハッシュ化はデータを匿名化しません。運用者は保存とネットワークメタデータとの関連付けを確認する必要があります。PPOIプロキシを参照してください。大量の履歴取得経路と異なり、POI 経路にはウォレット固有のクエリーがあります。

保護できないこと

  • 時刻と通信量。 全履歴を取得する初回同期と、先端だけを取得する再訪ウォレットでは通信の様子が異なります。そこから「このIPはブロックX付近で最後に同期した」と推測できますが、どのノートが自分のものかは明かしません。
  • 接続メタデータ。 直接接続を受けるサーバーには、IPアドレス、時刻、TLSメタデータが見えます。OHTTP中継はクライアント接続をリクエストを復号するゲートウェイから分離しますが、中継自体にはクライアントIPが見えます。
  • 上記のPPOI経路のブラインドされたコミットメント。

適切に設定したVPNやTorでネットワーク層の露出を減らせますが、信頼する相手が変わり、トラフィック分析やウォレット固有のアプリケーションデータがなくなるわけではありません。

ネットワークのプライバシーは、リクエストに含まれるウォレット固有の内容を消しません。

クエリベースのインデクサーでは、漏えいはアプリケーション層で起こり、利用者はウォレットを使わない以外に対処できません。均一で内容に依存しない履歴リクエストは、このフィルターの開示を避けます。ほかのウォレットリクエストやネットワークメタデータは、別に検討する必要があります。

トレードオフ

これはプライベート情報検索ではありません。隠すべきウォレット固有のリクエストがないため、暗号技術でリクエストを隠してはいません。匿名集合をダウンロードして自分で検索するだけです。その代わりに帯域幅を使います。初回同期では、数行の一致データではなく、圧縮されたプールの履歴を転送します。

この処理には適切なトレードオフです。データは公開され、変更されず、全ユーザーで同一なので、キャッシュに適しています。コストはユーザーごとではなく、各エッジ拠点の各ファイルにつき一度発生し、ある種類の開示をまとめて排除できます。ただし、チャンクの選択がユーザーに依存しない場合にだけ成り立ちます。ウォレットの内容から「必要な」範囲だけを取得すると、遅い形でクエリを再発明したことになります。そのため、チャンクの境界はブロック高だけで決めます。