Develop with pleasure!

福岡でCloudとかBlockchainとか。

ブラインドMuSig2

MuSig2は、n-of-nのマルチシグを暗号技術のみで構成するSchnorrベースのスクリプトレスなマルチシグスキーム↓

techmedia-think.hatenablog.com

そのブラインド版がブラインドMuSig2↓

https://github.com/halseth/ephemeral-signing-service/blob/main/doc/general.md

MuSig2の場合、通常署名者は

  • 何のメッセージに署名しているのか
  • 他の署名者の情報(公開鍵)

について知ることができる。ブラインド版は、これらの情報を秘密にしたまま有効なSchnorr署名を構成できるようにしたもの。

署名者であれば一般的には署名内容を把握した上で署名すべきだけど、こういったブラインド署名は、

などのケースにおいて有用な可能性がある。

ブラインドMuSig2

署名者が2人(アリスとボブ)いて、2-of-2のマルチシグを構成する場合、参加者の公開鍵を以下とする(小文字が秘密鍵)。

  •  {X_A = x_A G}
  •  {X_B = x_B G}

ブラインド版では、署名者が署名内容について知らずに署名をできるようにするためコーディネーターという役割を導入する。このコーディネーターは、署名対象のメッセージ(m)や、参加者、ブラインド係数などの情報を把握するが、署名者の協力がないと(=署名者の秘密鍵がないと)有効な署名を生成することはできない。

まずコーディネーターは、集約公開鍵を導出する。

ランダムなsalt値rを選択して以下の鍵係数を計算する(saltを使う理由は、署名者が候補となる公開鍵を総当たりで試して、誰と一緒に署名セッションに参加しているかを確認できないようにするため)。

  •  {l = H(r || X_A || X_B)}
  •  {c_A = H(l || X_A)}
  •  {c_B = H(l || X_B)}

続いて、鍵係数を使って集約公開鍵 {X' = c_AX_A + c_BX_B}を計算する。この集約公開鍵の計算自体は、通常のMuSig2と同じ計算。ただブラインド版では各署名者は互いの公開鍵を知らないため、コーディネーターのみが導出できる。各署名者は集約公開鍵を知らないため、オンチェーンにX'が登場しても自分が関与したトランザクションであることが認識できない。

続いて署名の生成。署名者のアリスとボブは、署名に使用する2つの公開ナンスを計算する:

  •  {R_A^{1} = r^{1}_AG} {R_A^{2} = r^{2}_AG}
  •  {R_B^{1} = r^{1}_BG} {R_B^{2} = r^{2}_BG}

コーディネーターは各署名者から受け取った公開ナンスを使って集約ナンスを計算する。

  •  {R^{1} = R_A^{1} + R_B^{1}}
  •  {R^{2} = R_A^{2} + R_B^{2}}

続いて、ナンスの係数 {b = H(R^{1} || R^{2} || X' || m)}を計算し、集約ナンスを {R = R^{1} + bR^{2}}とする。

公開ナンスの生成から集約ナンスの計算は、通常のMuSig2と同様。ただ署名に使われる最終的なナンスはブラインド値を加味した以下のR'になる。

続いて、ブラインド値 {\alpha_A, \beta_A, \alpha_B, \beta_B, \gamma_A, \gamma_B}を選択し、以下の署名ナンスを計算する:

 {R' = R + \gamma_A R^{2}_A + \gamma_B R^{2}_B + \beta_AX_A + \beta_BX_B + (\alpha_A + \alpha_B)G}

続いて署名対象のメッセージmを使って {e = H(R', X', m)}を計算する。

続いて、メッセージをブラインドするために各署名者に対して以下を行う(βはチャレンジeをブラインドし、γはブラインダーbをブラインドする)。

  • アリスに対して
    •  {e_A = c_Ae + \beta_A} {b_A = b + \gamma_A}を計算し、 {(e_A, b_A)}を送る。
  • ボブに対して
    •  {e_B = c_Be + \beta_B} {b_B = b + \gamma_B}を計算し、 {(e_B, b_B)}を送る。

このように、各署名者は署名するメッセージについて何も知らない。

各署名者は、以下のようにブラインド部分署名を計算する。

  • アリスの場合
    •  {s'_A = r^{1}_A + b_Ar^{2}_A + e_A x_A = r^{1}_A + (b + \gamma_A)r^{2}_A + ec_Ax_A + \beta_Ax_A}
  • ボブの場合
    •  {s'_B = r^{1}_B + b_Br^{2}_B + e_B x_B = r^{1}_B + (b + \gamma_B)r^{2}_B + ec_Bx_B + \beta_Bx_B}

各署名者からブラインド部分署名を受け取ったコーディネーターは、R'に対応させるため以下の加算を行う。

  •  {s_A = s'_A + \alpha_A}
  •  {s_B = s'_B + \alpha_B}

続いて、部分署名を合算して集約署名を計算する。

 {s = s_A + s_B}

 {\quad = s'_A + \alpha_A +  s'_B + \alpha_B}

 {\quad = r^{1}_A + (b + \gamma_A)r^{2}_A + ec_Ax_A + \beta_Ax_A + \alpha_A + r^{1}_B + (b + \gamma_B)r^{2}_B + ec_Bx_B + \beta_B x_B + \alpha_B}

 {\quad = (r^{1}_A + r^{1}_B) + b(r^{2}_A + r^{2}_B) + \gamma_A r^{2}_A + \gamma_B r^{2}_B + e(c_Ax_A + c_Bx_B) + \beta_Ax_A + \beta_Bx_B + (\alpha_A + \alpha_B)}

結果の(R', s)がメッセージmおよび集約公開鍵X'に対して有効なSchnorr署名となる。

この署名は以下の署名検証のチェックを満たす。

 {sG = (r^{1}_A + r^{1}_B)G + b(r^{2}_A + r^{2}_B)G + \gamma_A r^{2}_AG + \gamma_B r^{2}_BG}

 {\qquad + e(c_Ax_A + c_Bx_B)G + \beta_Ax_AG + \beta_Bx_BG + (\alpha_A + \alpha_B)G}

 {\quad = R^{1}_A + R^{1}_B + b(R^{2}_A + R^{2}_B) + \gamma_AR^{2}_A + \gamma_BR^{2}_B }

 {\qquad + e(c_AX_A + c_BX_B) + \beta_AX_A + \beta_BX_B + (\alpha_A + \alpha_B)G}

 {\quad = R +  \gamma_AR^{2}_A + \gamma_BR^{2}_B + \beta_AX_A + \beta_BX_B + (\alpha_A + \alpha_B)G + e(X'_A + X'_B)}

 {\quad = R' + eX'}

検証式から分かるように、ブラインド値はすべて署名ナンスR'で回収される。

ブラインド値の {\alpha_A, \alpha_B}については、おそらくオンチェーン上のTxを監視してそれらの署名値などと組み合わせて事後分析などできないようにするためのブラインド値と思われるけど、いずれもコーディネーター側でしか計算には使わないので1つあれば十分な気がする。

課題と信頼モデル

MuSig2の設計上の重要な点は、鍵係数(l)とブラインド値(b)の選択。通常のMuSig2の場合、すべての署名者が係数が適切に構成されていることを検証できるけど、ブラインド版ではこれらの値がブラインド化されているため署名者の検証が不可能になる。そのため上記のブラインドモデルはコーディネーターを信頼するモデルとなる。

コーディネーターに悪意がある場合、署名すべきではないメッセージに署名させたり、それにより鍵情報が漏洩する可能性もある。