はじめに
この記事では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(h0∥h1)h0=Hash(h00∥h01)h1=Hash(h10∥h11)
と表す。
セキュリティパラメータをλ
として
離散対数をオーダーp(λ)
で解くことができるアルゴリズムが確率neg(λ)
を除いて存在しない巡回群G=⟨G⟩
と
アウトプットの長さがq(λ)
のランダムオラクルとしてモデリングされた2つのハッシュ関数Hpk
,Hm
を定義する。
離散対数の定義は以下。
b
をG
の生成元とすれば、∀g∈G
はk∈N,g=bk
と表せる。
またg
を表現する2つの整数k1,k2
はn
を法として合同だから、
logb:G→N/nN
なる関数を定義でき、b
を底とする離散対数と定義する。
また、β=(KeyGenβ,Signβ,Verifyβ)
を署名スキームとする。
またランダムオラクルの定義は以下。
H:{0,1}l→{0,1}k
が以下を満たす時Hをランダムオラクルと呼ぶ。
1.過去に定めたH(x)
は一意に決定され
2.H(x)
が未定義のときには{0,1}k
からランダムに値を決める。
("デジタル署名の証明可能安全性"より)
定理の証明では、攻撃者と挑戦者の間のゲームを想定する。
このゲームでは、「挑戦者が用意した署名値」を攻撃者が偽造しようとする。(暗号系の安全性検証)
Taprootのアルゴリズムにおける公開鍵
下図のroot
の値をt
として公開鍵Q=P+tG
ただしhashtag(m)=SHA256(SHA256(tag)∥SHA256(tag)∥m)

出典:https://qiita.com/tnakagawa/items/0ca27450331183ea3509
安全性の証明におけるアルゴリズムの定義
TRβ
と記述されるβ
のTaprootを以下4つのアルゴリズムとして定義する。
1 鍵生成
KeyGen(b)
はbit-b
を入力して、keypair(sk0,sk1,pk)
を出力する。
まず、skα$Z/p(λ)Z
を選択し、
pkα$skαG(λ)
を計算する。
もしb=0
ならば、アウトプットは(skα,⊥,pkα)
もしb=1
ならば、(skβ,pkβ)←KeyGenβ
で
ε←Hpk(pkβ∥pkα)
このときアウトプットsk0←skα+εsk1=(skβ,pkα,pkβ)pk←pkα+εG
2 署名出力1
Sign1(sk0,m)
は秘密鍵sk0
,メッセージm
を入力しアウトプットである署名σ
を以下のように出力する。
k$Z/p(λ)ZR←kGpk←sk0Ge←Hm(pk∥R∥m)
を計算し σ=(R,k+esk0)
を出力する。
3 署名出力2
Sign2(sk1=(skβ,pkα,pkβ),m)
は秘密鍵sk1
,メッセージm
を入力し、署名σ
を以下のように出力する。 σβ=Signβ(skβ,m)
を計算し、σ=(pkα,pkβ,σβ)
を出力する。
4 検証
Verify(pk,σ,m)
は公開鍵pk
,署名σ
,メッセージm
を入力しbitb
を以下のように出力する。
もしσ=(R,s)
ならばe←Hm(pk∥R∥m)
を計算し、sG=R+epk
のときに限り受諾する。 もしσ=(pkα,pkβ,σβ)
ならば、まず pk=pkα+Hpk(pkβ∥pkα)G
を確認し、もしそうならば、Verifyβ(pkβ,σβ,m)
のときに限り受諾する。
定理
定理1
もし離散対数問題がG
において困難かつ、β
が偽造不可能ならば、TRβ
は敵対者A
と挑戦者C
の間で以下のゲームにおいて偽造不可能である。
ゲーム
敵対者A
が bitb
を選び、挑戦者C
に送信する。C
はKeyGen(b)
により生成された公開鍵pk
を返す。
A
は、 i∈{1,2,...,q},λ
についての多項式で拘束されるq
に対して定義される署名クエリ(bi,mi)
を送信する。 C
はSignb
により生成される有効な署名σi
を返す。
A
はVerify(pk,σ∗,m∗)
が受諾されるような署名(σ∗,m∗)
を再送する。
もしβ
が存在的偽造不可能(existentially unforgeable)ならば全てのi
に対して(σ∗,m∗)=(σi,mi)
を得る。 そうでなければ全てのi
に対してm∗=mi
を得られる。
解説
要するに、攻撃者はTaprootの鍵パスとスクリプトパスそれぞれについて、セキュリティパラメータが許す限りいくらでも事前に任意のメッセージに対する有効な署名を入手できる。この得られた有効な署名の情報を使って新しい有効な署名を作り出すことができれば攻撃者が勝利する。
ただし、新しい有効な署名はこれまでに得られたメッセージと署名のペアをそのまま提出してはならない。また、存在的偽造不可能でない場合は、メッセージだけを改変して署名を偽造することもできないはずである。
証明
この定理の証明は2つの補題からなる。
安全性の証明では以下のような方法が使われることに注意せよ。
暗号方式が用いられるときに妥当な情報を入手できる攻撃者が、
攻撃に成功したときに矛盾が生じることを示すやり方が用いられる。
http://www.tj.chiba-u.jp/~wkishi/cryptography.htmlhttp://www.tj.chiba-u.jp/~wkishi/cryptography.html
補題1
敵対者A
が確率ε
でSign2
の形で偽造をアウトプットするならば、確率ε−neg(λ,q)
でβ
の偽造を生成できる。
補題1の証明
β
-挑戦者にアクセスできる挑戦者C
、敵対者A
の存在を仮定する。
まずC
は全てのランダムオラクルクエリに一様に独立に返答する。
C
は独立でランダムな鍵ペア(skα,pkα)
を選択する。
・もしb=0
ならば、C
はpkα
をA
に送信しsk=skα
と保存する。
・もしb=1
ならば、C
は公開鍵pkβ
をβ
挑戦者に要求し、pk=pkα+Hpk(pkβ∥pkα)G
を計算し、A
に送信する。
C
はsk=skα+Hpk(pkβ∥pkα)
と保存する。
署名クエリ(bi,mi)
が与えられると、A
は以下のように振る舞う。
もしbi=0
ならばSign1(sk,mi)
を実行しσi
を返す。
もしbi=1
かつb=0
ならば⊥
を返す。
もしbi=1
かつb=1
ならばβ
挑戦者にmi
の問い合わせをしてσIβ
を獲得し、σi=(pkα,pkβ,σβ)
を返答する。
最後にA
はSign2
の形でσ∗=(pk∗α,pk∗β,σ∗β)
を満たす署名(σ∗,m∗)
を返す。
更に、σ∗β
は鍵pk∗β
とpk=pk∗α+Hpk(pk∗β∥pk∗α)G
と共にm∗
に有効な署名となる。
まず、Hpk
がランダムオラクルとしてモデリングされ、A
は多項式回問い合わせすることより(pk∗α,pk∗β)=(pkα,pkβ)
がごく僅かな確率を除いて成り立つ。
ゆえに、
(σ,m∗)
がTR∗β
の偽造であるときに限り(σ∗β,m∗)
がβ
の偽造となるように、σ∗β=σiβ
のときに限りσ∗=σi
が成り立つ。
補題2
敵対者A
が確率ε
でSign1
の形で偽造をアウトプットするならば、確率ε−neg(λ,q)
で(G,G,Hm)
でのシュノア署名の偽造を生成できる。
補題2の証明
C
は以下のように振る舞う。
まず、ランダムオラクルHS
へのアクセスでき、s=R+eP,P=HS(P∥R∥m)
を満たす署名(s,R)
を期待するシュノア署名への挑戦者S
にアクセスできる。
β
挑戦者にアクセスできる敵対者A
の存在を仮定する。
まずC
は全てのランダムオラクルクエリに一様に独立に返答する。
もしb=0
ならばC
はS
からA
に公開鍵を転送し、全てのbi=1
の署名に⊥
を返し、
それ以外の場合には、全ての署名をS
に、Hm
のクエリをHS
に転送し、得られた偽造をシュノア偽造として提示する。
Sign1(sk,mi)
を実行しσi
を返す。
もしbi=1
かつb=0
ならば⊥
を返す。
このとき証明はすぐに得られるので、以下b=1
の場合の証明を行う。
C
はS
から公開鍵pkα
を得られ、(skβ,pkβ)← KeyGenβ
を選び、pk=pkα+Hpk(pkβ∥pkα)G
を計算する。C
はA
にpk
を送信する。
C
はHpk
クエリに一様にランダムに返答する。C
はpk
をpkα
に置き換えてHm
クエリに返答する。その逆の場合はHS
クエリに転送する。
C
は署名クエリ(bi,mi)
に以下のように返答する。
もしbi=1
ならばC
はSign2
の形でσi←Sign2((skβ,pkα,pkβ),mi)
を得られ、返す。
もしbi=0
ならばC
はS
からmi
に関する署名(si,Ri)
を要求する。
ei=HS(pkα∥R∥mi)
として、C
はeiHpk(pkβ∥pkα)
をsi
に加えsi′
を得られ、σi=(si′,Ri)
を返答する。
si′G=siG+eiHpk(pkβ∥pkα)G=Ri+ei(pkα+Hpk(pkβ∥pkα)G)=Ri+eipk
より、
σi
は有効な署名となる。
しかしC
のHm
への返答により、ei=HS(pkα∥R∥mi)=Hm(pk∥R∥mi)
が保証され、これはTRβ
の検証式となる。
A
はSign1
の形で∀i,(σ∗,m∗)=(σi,mi)
を満たす偽造(σ∗,m∗)
を返し、Verify(pk,σ∗,m∗)
を受諾する。
(s∗−e∗Hpk(pkβ∥pkα))G=R∗+e∗pk−Hpk(pkβ∥pkα)G=R∗+e∗pkα
から(s∗−e∗Hpk(pkβ∥pkα),R∗)
が有効なシュノア署名で、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