zk-Email
概要
web2-web3の統合が大きなビジョン
web2上の署名の証明をオンチェーンでやろう!って感じ
メールの署名を検証するZKPを作成し、ユーザーが選択したアドレスのみがこの証明を使用してメールの所有権を確認できる
例
rsa_sign(sha256(from:<>, to:<>, subject:<>, ,...), @mit.edu key)
MITの学生が持つすべてのメールに、このRSA署名が付いているとする。
例えば、ユーザーyがx@mit.edu から y@mit.edu までの任意のメールヘッダを提供した時、検証者は mit.edu の公開鍵を取得し、署名を検証することができる。
ZKでこれを行えば、ユーザーy以外の誰も、それが誰であるかを決定できないようにアプリケーションを設計することができる
証明生成やウェブサイトは、100%クライアントサイド
回路
ZK Proof Public:
sender domain and receiver domain
the RSA modulus
the masked message (can be domains, or part of message)
ZK Proof Private:
the dkim signature from the mail server
the length of the pre-hashed message data
the raw message data
ZK Circuit Checks:
sha256 and RSA both verify
SHA256はS/MIMEにも関係がある
the message is well structured via regex
the chosen regex state matches the mask provided
Contract Checks:
sender domain == receiver domain
claimed RSA key == DNS-fetched/cached RSA key
面白い点
ZKでこれらのメールを効率的に検証するために以下の発明が生まれた。
1. 同じ検証回路ですべてのメッセージの長さを検証すること
circomlibのSHA256回路を改良して任意長のSHA256を設計することで解決
電子メールは非常に長いので、回路が実現不可能なほど長くなる可能性があります。viv_boopからのヒントで、メールの終わり近くで値を証明したい場合、ハッシュ関数の部分的なpre-imageを渡して、ZK-SNARKの内部で最後の数ブロックのハッシュだけを実行すればよいことに気づきました。これは、部分的なハッシュを計算できるようにするために、完全なpre-imageを知る必要があるために有効です。このトリックは、スポンジベースやMerkle-Damgardベースのハッシュ関数にも有効で、ハッシュpre-imageの知識があれば、どこでもハッシュ検証を高速化することができます!
らしい
2. システムをハックしてメールをごまかすことができないことを保証する
ZK SNARK 内でメールクライアントと全く同じ方法でフィールドを解析する必要がある。
circomの正規表現を設計することで解決。
zk JSON validate的なこともできそうでは?
以下、その仕組みの説明
例えば、誰かがメールの件名に自分のフィールドを詰め込んで、"subject: to: aayushg@mit.edu "のように送信するのをどうやって止めるのでしょうか。
本当の宛先について混乱する
幸いなことに、フィールド(宛先フィールド、CCフィールドなど)間の区切り文字として標準的に使用されている「 \r\n 」は、偽装しようとするとテキストがエスケープされる。つまり、ユーザーが入力した「 \r\n 」は「 \r\n 」として表示される。
これをテキストマッチングと組み合わせて、メールフィールドの妥当性を効果的にチェックすることができます。
例: Appleのメールアプリで楽天ペイからのメールのヘッダを表示させるとこんな感じ
code:mail-header
宛先: 津田匠貴 <shoukitsuda@icloud.com>
Content-Type: text/html; charset="utf-8"
Sender: checkout@bounce.emagazine.rakuten.co.jp
ヘッダーチェックでは、エスケープされた「from:」メールが実際に@twitter.comであることを確認します。偽の情報をフィールドに詰め込むことを避けるために、ヘッダーのfromの前にある \r\n をチェックします:メールクライアントは常にユーザーテキストを \rn としてエスケープするので、これは詰め込んだり偽造したりすることはできません。
circom内部で任意の正規表現チェックを行うために、最も効率的な方法はcircomコードをオンザフライで自動生成することである。正規表現が機能する方法は、DAGベースのデータ構造を使用し、文字遷移ごとにDFA:決定性有限オートマトンの右端をトラバースすることによって、文字列の各文字に関連する正規表現の「状態」を更新します。DFA が成功状態で終了すれば、正規表現にマッチしたことになります。正規表現にマッチした特定のテキストを抽出するには、特定のDFAの状態を分離し、その値のみを明らかにするために文字列全体をマスクすればよいのです。このように、任意の正規表現をDFAに変換し、そのDFAをゲート操作で表現する短いPythonプログラムをcircomコードに実装しました。 このcircom制約への移行は、初等的なゲートを介して行われます。順番に各文字で、現在の文字と前の文字の状態を比較し、一連のANDと多重ORゲートを通して、現在の状態がどうあるべきかを推論します。つまり、zkeyを導き出す前に正規表現の構造を知っておく必要があります(ただし、マッチする特定の文字はその場で編集することができます)。
前提
1.DNSの公開鍵
DNSキーはDNSレコードから取得する必要があり、6ヶ月から2年ごとに更新されます。現在、コントラクトには平文で記載されており、目視で確認することができますが、将来的には、ウェブサイトがより安全なフレームワークを選択するように、DNSSECで信頼性の高い検証を行うことを望んでいます。
2.送信側メールサーバ
送信側のメールサーバは、秘密鍵を所有しているので、どんな偽メッセージでも偽造できる。しかし、そのような鍵を持つ敵は、そのドメインの誰からでも好きなメールを送ることができる。したがって、メールが信頼できるようにするためには、これを避けるための十分なチェックとバランスが理想的であると考えられる。さらに、送信側のメールサーバは自由にメールフォーマットを変更でき、それを解析するための既存のzk正規表現を壊して、一時的にzkメール検証を無効にして、システムが新しい正規表現に適応するためにzkeyの再コンパイルを必要とします。
3.受信側メールサーバ
このサーバはヘッダだけでなく平文であなたのメールをすべて読むことができるので、受信側メールサーバの鍵を持つ誰かがドメイン内の誰に対しても本当の証明を送ることができます(例えば、Gmailはあなたのメールをすべて読むことができます)。幸運なことに、誰でもこれに対抗するためにS/MIME標準を使うことができます。広く採用されるまでは、メールサーバがこの力を乱用しないことを望みます(メールサーバがあなたのメールを読んだり、あなたからのメールを偽装していないことをあなたはすでに信頼しているので、おおむね私たちはすでにこれを想定しているのです)。 もしメッセージに無効化文字(Twitterのハンドルネーム、本文のハッシュなど)があれば、メールサーバはチェーン上の人々の匿名化を解除することができるようになります。
FAQ
署名のための公開鍵はどこで手に入りますか?
通常、親組織の下のどこかのURLでホストされているはずです。.pemファイルから取得することもできますが、このようなファイルのエンコーディングは大きく異なり、特異で、解析が困難なため、通常、困難な作業となります。最も簡単な方法は、RSA署名自体からそれを抽出し、それが親組織と一致するかどうかを検証することです。
正しい公開鍵の検証をどのように信頼すればよいのですか?
Solidity検証ツールで分解された公開鍵を見ることができ、これをメールサーバーのURLと照合して自動チェックすることができます。これにより、DNSスプーフィング攻撃の犠牲となるコードを防ぐことができます。メールサーバーのキーローテーションについては、今はまだ考えていませんが、DNSSEC(広く有効になっていませんが)または別のコントラクトを展開することによって、信頼できる形で行えるようになると思います。
参考文献