Loading [MathJax]/extensions/tex2jax.js

Bitcoinのアップデート「Taproot」は本当に安全なのか?

お知らせ
Table of Contents

はじめに

この記事ではTaprootの安全性の証明を述べます。 まず、Taprootの歴史、記号の定義、アルゴリズムを述べます。
次に、安全性の証明におけるTaprootのアルゴリズムを定義し、定理を述べ最後にその証明を行います。

Taprootの歴史

Bitcoinのアウトプットに設定されるScriptのサイズを小さくし(効率化)、
不使用のScriptを公開しないよう(プライバシー)提案されたのがTaprootである。

2018年1月に、Bitcoin Core開発者かつBlockstream社の元CTOであるGregory Maxwellにより、Taprootは提案された。
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html

次に2018年4月に、今回扱うAndrew Poelstraによる安全性の証明が公開された。
https://github.com/apoelstra/taproot/blob/master/main.pdf

記号の定義


以上のようなマークルツリーを考えるときに、
h=Hash(h0h1)h0=Hash(h00h01)h1=Hash(h10h11)h=Hash(h_0\|h_1)\\h_0=Hash(h_00\|h_01)\\h_1=Hash(h_10\|h_11)
と表す。
セキュリティパラメータをλ\lambdaとして
離散対数をオーダーp(λ)p(\lambda)で解くことができるアルゴリズムが確率neg(λ)neg(\lambda)を除いて存在しない巡回群G=G\mathscr{G}=\langle G \rangle
アウトプットの長さがq(λ)q(\lambda)のランダムオラクルとしてモデリングされた2つのハッシュ関数HpkH^{pk},HmH^mを定義する。

離散対数の定義は以下。
bbGGの生成元とすれば、gG \forall g \in G kN,g=bkk \in \mathbb{N} , g=b^kと表せる。
またggを表現する2つの整数k1,k2k_1,k_2nnを法として合同だから、
logb:GN/nN\\log_b:G\rightarrow \mathbb{N}/n\mathbb{N} なる関数を定義でき、bbを底とする離散対数と定義する。

また、β=(KeyGenβ,Signβ,Verifyβ)\beta=(KeyGen^\beta,Sign^\beta,Verify^\beta)を署名スキームとする。

またランダムオラクルの定義は以下。

H:{0,1}l{0,1}kH:\{0,1\}^l\rightarrow \{0,1\}^kが以下を満たす時Hをランダムオラクルと呼ぶ。
1.過去に定めたH(x)H(x)は一意に決定され
2.H(x)H(x)が未定義のときには{0,1}k\{0,1\}^kからランダムに値を決める。
("デジタル署名の証明可能安全性"より)

定理の証明では、攻撃者と挑戦者の間のゲームを想定する。

このゲームでは、「挑戦者が用意した署名値」を攻撃者が偽造しようとする。(暗号系の安全性検証)

Taprootのアルゴリズムにおける公開鍵

下図のrootrootの値をttとして公開鍵Q=P+tGQ=P+tG
ただしhashtag(m)=SHA256(SHA256(tag)SHA256(tag)m)hash_{tag}(m)=SHA256(SHA256(tag)\|SHA256(tag)\|m)


出典:https://qiita.com/tnakagawa/items/0ca27450331183ea3509

安全性の証明におけるアルゴリズムの定義

TRβTR^\betaと記述されるβ\betaのTaprootを以下4つのアルゴリズムとして定義する。

1 鍵生成

KeyGen(b)KeyGen(b)はbit-bbを入力して、keypair(sk0,sk1,pk)(sk_0,sk_1,pk)を出力する。
まず、skα$Z/p(λ)Zsk^\alpha\xleftarrow{\char36 }\mathbb{Z}/p(\lambda)\mathbb{Z}を選択し、
pkα$skαG(λ)pk^\alpha\xleftarrow{\char36 }sk^\alpha{G(\lambda)}を計算する。
もしb=0b=0ならば、アウトプットは(skα,,pkα)(sk^\alpha,\bot,pk^\alpha)
もしb=1b=1ならば、(skβ,pkβ)KeyGenβ(sk^\beta,pk^\beta)\leftarrow KeyGen^\beta
εHpk(pkβpkα)\varepsilon\leftarrow H^{pk}(pk^\beta\|pk^\alpha)
このときアウトプットsk0skα+εsk1=(skβ,pkα,pkβ)pkpkα+εGsk_0\leftarrow sk^\alpha + \varepsilon\\sk_1=(sk^\beta,pk^\alpha,pk^\beta)\\pk\leftarrow pk^\alpha+\varepsilon G

2 署名出力1

Sign1(sk0,m)Sign^1(sk_0,m)は秘密鍵sk0sk_0,メッセージmmを入力しアウトプットである署名σ\sigmaを以下のように出力する。
k$Z/p(λ)ZRkGpksk0GeHm(pkRm)k\xleftarrow{\char36 }\mathbb{Z}/p(\lambda)\mathbb{Z}\\R\leftarrow kG\\pk\leftarrow sk_0G\\e\leftarrow H^m(pk\|R\|m)を計算し σ=(R,k+esk0)\sigma=(R,k+esk_0)を出力する。

3 署名出力2

Sign2(sk1=(skβ,pkα,pkβ),m)Sign^2(sk_1=(sk^\beta,pk^\alpha,pk^\beta),m)は秘密鍵sk1sk_1,メッセージmmを入力し、署名σ\sigmaを以下のように出力する。 σβ=Signβ(skβ,m)\sigma^\beta=Sign^\beta(sk^\beta,m)を計算し、σ=(pkα,pkβ,σβ)\sigma=(pk^\alpha,pk^\beta,\sigma^\beta)を出力する。

4 検証

Verify(pk,σ,m)Verify(pk,\sigma,m)は公開鍵pkpk,署名σ\sigma,メッセージmmを入力しbitbbを以下のように出力する。
もしσ=(R,s)\sigma=(R,s)ならばeHm(pkRm)e\leftarrow H^m(pk\|R\|m)を計算し、sG=R+epksG=R+epkのときに限り受諾する。 もしσ=(pkα,pkβ,σβ)\sigma=(pk^\alpha,pk^\beta,\sigma^\beta)ならば、まず pk=pkα+Hpk(pkβpkα)Gpk=pk^\alpha+H^{pk}(pk^\beta\|pk^\alpha)Gを確認し、もしそうならば、Verifyβ(pkβ,σβ,m)Verify^\beta(pk^\beta,\sigma^\beta,m)のときに限り受諾する。

定理

定理1

もし離散対数問題がG\mathscr{G}において困難かつ、β\betaが偽造不可能ならば、TRβTR^\betaは敵対者A\mathscr{A}と挑戦者C\mathscr{C}の間で以下のゲームにおいて偽造不可能である。

ゲーム

敵対者A\mathscr{A}が bitbbを選び、挑戦者C\mathscr{C}に送信する。C\mathscr{C}KeyGen(b)KeyGen(b)により生成された公開鍵pkpkを返す。

A\mathscr{A}は、 i{1,2,...,q},λi\in \{1,2,...,q\},\lambdaについての多項式で拘束されるqqに対して定義される署名クエリ(bi,mi)(b_i,m_i)を送信する。 C\mathscr{C}SignbSign^bにより生成される有効な署名σi\sigma_iを返す。

A\mathscr{A}Verify(pk,σ,m)Verify(pk,\sigma_*,m_*)が受諾されるような署名(σ,m)(\sigma_*,m_*)を再送する。
もしβ\betaが存在的偽造不可能(existentially unforgeable)ならば全てのiiに対して(σ,m)(σi,mi)(\sigma_*,m_*)≠(\sigma_i,m_i)を得る。 そうでなければ全てのiiに対してmmim_*≠m_iを得られる。

解説

要するに、攻撃者はTaprootの鍵パスとスクリプトパスそれぞれについて、セキュリティパラメータが許す限りいくらでも事前に任意のメッセージに対する有効な署名を入手できる。この得られた有効な署名の情報を使って新しい有効な署名を作り出すことができれば攻撃者が勝利する。
ただし、新しい有効な署名はこれまでに得られたメッセージと署名のペアをそのまま提出してはならない。また、存在的偽造不可能でない場合は、メッセージだけを改変して署名を偽造することもできないはずである。

証明

この定理の証明は2つの補題からなる。

安全性の証明では以下のような方法が使われることに注意せよ。

暗号方式が用いられるときに妥当な情報を入手できる攻撃者が、
攻撃に成功したときに矛盾が生じることを示すやり方が用いられる。
http://www.tj.chiba-u.jp/~wkishi/cryptography.htmlhttp://www.tj.chiba-u.jp/~wkishi/cryptography.html

補題1

敵対者A\mathscr{A}が確率ε\varepsilonSign2Sign^2の形で偽造をアウトプットするならば、確率εneg(λ,q)\varepsilon - neg(\lambda,q)β\betaの偽造を生成できる。

補題1の証明

β\beta-挑戦者にアクセスできる挑戦者C\mathscr{C}、敵対者A\mathscr{A}の存在を仮定する。
まずC\mathscr{C}は全てのランダムオラクルクエリに一様に独立に返答する。

C\mathscr{C}は独立でランダムな鍵ペア(skα,pkα)(sk^\alpha,pk^\alpha)を選択する。
・もしb=0b=0ならば、C\mathscr{C}pkαpk^\alphaA\mathscr{A}に送信しsk=skαsk=sk^\alphaと保存する。
・もしb=1b=1ならば、C\mathscr{C}は公開鍵pkβpk^\betaβ\beta挑戦者に要求し、pk=pkα+Hpk(pkβpkα)Gpk=pk^\alpha +H^{pk}(pk^\beta\|pk^\alpha)Gを計算し、A\mathscr{A}に送信する。
C\mathscr{C}sk=skα+Hpk(pkβpkα)sk=sk^\alpha +H^{pk}(pk^\beta\|pk^\alpha)と保存する。

署名クエリ(bi,mi)(b_i,m_i)が与えられると、A\mathscr{A}は以下のように振る舞う。
もしbi=0b_i=0ならばSign1(sk,mi)Sign^1(sk,m_i)を実行しσi\sigma_iを返す。
もしbi=1b_i=1かつb=0b=0ならば\botを返す。
もしbi=1b_i=1かつb=1b=1ならばβ\beta挑戦者にmim_iの問い合わせをしてσIβ\sigma^\beta_Iを獲得し、σi=(pkα,pkβ,σβ)\sigma_i=(pk^\alpha,pk^\beta,\sigma^\beta)を返答する。

最後にA\mathscr{A}Sign2Sign^2の形でσ=(pkα,pkβ,σβ)\sigma_*=(pk^\alpha_*,pk^\beta_*,\sigma^\beta_*)を満たす署名(σ,m)(\sigma_*,m_*)を返す。
更に、σβ\sigma^\beta_*は鍵pkβpk^\beta_*pk=pkα+Hpk(pkβpkα)Gpk=pk^\alpha_* +H^{pk}(pk^\beta_*\|pk^\alpha_*)Gと共にmm_*に有効な署名となる。
まず、HpkH^{pk}がランダムオラクルとしてモデリングされ、A\mathscr{A}は多項式回問い合わせすることより(pkα,pkβ)=(pkα,pkβ)(pk^\alpha_*,pk^\beta_*)=(pk^\alpha,pk^\beta)がごく僅かな確率を除いて成り立つ。
ゆえに、
(σ,m)(\sigma,m_*)TRβTR^\beta_*の偽造であるときに限り(σβ,m)(\sigma^\beta_*,m_*)β\betaの偽造となるように、σβ=σiβ\sigma^\beta_*=\sigma^\beta_iのときに限りσ=σi\sigma_*=\sigma_iが成り立つ。

補題2

敵対者A\mathscr{A}が確率ε\varepsilonSign1Sign^1の形で偽造をアウトプットするならば、確率εneg(λ,q)\varepsilon - neg(\lambda,q)(G,G,Hm)(\mathscr{G},G,H^m)でのシュノア署名の偽造を生成できる。

補題2の証明

C\mathscr{C}は以下のように振る舞う。
まず、ランダムオラクルHSH^Sへのアクセスでき、s=R+eP,P=HS(PRm)s=R+eP,P=H^S(P\|R\|m)を満たす署名(s,R)(s,R)を期待するシュノア署名への挑戦者S\mathscr{S}にアクセスできる。
β\beta挑戦者にアクセスできる敵対者A\mathscr{A}の存在を仮定する。
まずC\mathscr{C}は全てのランダムオラクルクエリに一様に独立に返答する。
もしb=0b=0ならばC\mathscr{C}S\mathscr{S}からA\mathscr{A}に公開鍵を転送し、全てのbi=1b_i=1の署名に\botを返し、
それ以外の場合には、全ての署名をS\mathscr{S}に、HmH^mのクエリをHSH^Sに転送し、得られた偽造をシュノア偽造として提示する。

Sign1(sk,mi)Sign^1(sk,m_i)を実行しσi\sigma_iを返す。
もしbi=1b_i=1かつb=0b=0ならば\botを返す。
このとき証明はすぐに得られるので、以下b=1b=1の場合の証明を行う。

C\mathscr{C}S\mathscr{S}から公開鍵pkαpk^\alphaを得られ、(skβ,pkβ) KeyGenβ(sk^\beta,pk^\beta)\leftarrow KeyGen^\betaを選び、pk=pkα+Hpk(pkβpkα)Gpk=pk^\alpha +H^{pk}(pk^\beta\|pk^\alpha)Gを計算する。C\mathscr{C}A\mathscr{A}pkpkを送信する。

C\mathscr{C}HpkH^{pk}クエリに一様にランダムに返答する。C\mathscr{C}pkpkpkαpk^\alphaに置き換えてHmH^{m}クエリに返答する。その逆の場合はHSH^{S}クエリに転送する。

C\mathscr{C}は署名クエリ(bi,mi)(b_i,m_i)に以下のように返答する。
もしbi=1b_i=1ならばC\mathscr{C}Sign2Sign^2の形でσiSign2((skβ,pkα,pkβ),mi)\sigma_i\leftarrow Sign^2 ((sk^\beta,pk^\alpha,pk^\beta),m_i)を得られ、返す。
もしbi=0b_i=0ならばC\mathscr{C}S\mathscr{S}からmim_iに関する署名(si,Ri)(s_i,R_i)を要求する。
ei=HS(pkαRmi)e_i=H^S(pk^\alpha\|R\|m_i)として、C\mathscr{C}eiHpk(pkβpkα)e_iH^{pk}(pk^\beta\|pk^\alpha)sis_iに加えsis_i^\primeを得られ、σi=(si,Ri)\sigma_i=(s_i^\prime,R_i)を返答する。
siG=siG+eiHpk(pkβpkα)G=Ri+ei(pkα+Hpk(pkβpkα)G)=Ri+eipks_i^\prime G=s_iG+e_iH^{pk}(pk^\beta\|pk^\alpha)G\\=R_i+e_i(pk^\alpha +H^{pk}(pk^\beta\|pk^\alpha)G)\\=R_i+e_ipk
より、
σi\sigma_iは有効な署名となる。
しかしC\mathscr{C}HmH^mへの返答により、ei=HS(pkαRmi)=Hm(pkRmi)e_i=H^S(pk^\alpha\|R\|m_i)=H^m(pk\|R\|m_i)が保証され、これはTRβTR^\betaの検証式となる。

A\mathscr{A}Sign1Sign^1の形でi,(σ,m)(σi,mi)\forall i,(\sigma_*,m_*)≠(\sigma_i,m_i)を満たす偽造(σ,m)(\sigma_*,m_*)を返し、Verify(pk,σ,m)Verify(pk,\sigma_*,m_*)を受諾する。
(seHpk(pkβpkα))G=R+epkHpk(pkβpkα)G=R+epkα(s_*-e_*H^{pk}(pk^\beta\|pk^\alpha))G\\=R_*+e_*pk-H^{pk}(pk^\beta\|pk^\alpha)G\\=R_*+e_*pk^\alphaから(seHpk(pkβpkα),R)(s_*-e_*H^{pk}(pk^\beta\|pk^\alpha),R_*)が有効なシュノア署名で、S\mathscr{S}に対する署名クエリの出力と等しくない。

まとめ

補題1と補題2より、鍵パスとスクリプトパスどちらのケースであっても、定理1で偽造ができてしまうとシュノア署名自体の偽造ができてしまうことが分かる。したがって、Taprootの署名スキームはシュノア署名のスキーム自体と同程度に安全である。

感想

補題1,2両方とも敵対者の行動が不必要に制限されているように見え、本当にこの証明で安全性が示せているのかは疑問に感じた。

参考文献

https://github.com/apoelstra/taproot/blob/master/main.pdf

https://www.ieice.org/~isec/event/isec050517/isec05051703.pdf

Merkle Tree - MOXBOX #merkletree #hash
マークルツリー (Merkle tree; ハッシュ木) はあるデータセットのハッシュ値を再帰的にハッシュ化することで得られる ツリー構造。このツリーのルートにあたるルートハッシュはすべてのデータのハッシュ特性を含んだ固定サイズの値であるため、後で一部のデータを 検証するのに都合が良い。
https://www.jstage.jst.go.jp/article/jssst/33/4/33_4_67/_pdf
タイトルとURLをコピーしました