ブロックチェーンでよく使われる技術要素の1つとしてコミットメントスキームが挙げられる。シンプルなコミットメントスキームのユースケースとしては、OpenTimestampなど。BitcoinであればOP_RETURN
opcodeを使ってファイルのハッシュを記録することで、そのファイルの存在証明を提供することができる。
他にもある契約に関する支払いを行う際に、その契約にコミットした支払いであることを表現するのに利用できるPay to contractのようなプロトコルもある↓
techmedia-think.hatenablog.com
Pay to contractでは、契約内容のハッシュ値と受信者の公開鍵から新しい公開鍵を作成し、その公開鍵宛に支払いを行うことで、契約内容にコミットした支払いを表現する。これは楕円曲線の鍵の準同型性を利用したもので、OP_RETURN
で記録するアプローチと比較すると、オンチェーン上のフットプリントを増やすくことなくコミットできるのがポイントだ。
BitcoinのBIPでは、Pay to contractベースの支払いのアドレスを決定論的に導出する仕様(BIP-175)も提案されている↓
techmedia-think.hatenablog.com
そんなコミットメントスキームについて、最近Sign to contractというスキームを耳にしたのでどんなスキームなのかみてみよう↓
Pay to contractの課題
Pay to contractにより、ブロックチェーンに追加のフットプリントを課すことなく、通常の支払いで任意のデータへのコミットもできるようになるが、状況によっては課題が生じる場合もある。
例えば、受信者の鍵ペアをP = xGとし、コミットメントしたい契約内容のハッシュ値をdとした場合、Pay to contractの受信アドレスQは、以下のように計算される(H()は暗号学的ハッシュ関数、Gは楕円曲線のジェネレータ、||は結合)。
Q = H(P || d)G + P
アドレスQに送られたコインを使用するためには、H(P || d)とPの秘密鍵xの情報が必要になる。
この内、xはHDウォレットなどの仕組みで決定論的に導出することができるため、シードさえバックアップ取っていれば、バックアップから復元することが可能だが、dのデータはそのように決定論的に導出できるものではなく、契約単位に変わるデータになるだろう。そのため、dのデータについては別途バックアップが必要になる。このバックアップが失われるとQにロックされたコインは取り出せなくなってしまう。
Sign to contract
Pay to contractでは、受信アドレスにコミットメントを含めるアプローチであるため、↑のような課題が発生するが、Sign to contractでは受信アドレスではなく署名データにコミットメントを含めるというアプローチで、この課題を解消する。
ECDSAの署名スキーム
鍵ペアP = xG、署名対象のメッセージをm(通常はトランザクションデータ)とした場合、Pとmに対して有効なECDSA署名は、一般的に以下の手順で作成される。
Sign to contractの署名スキーム
Sign to contractでは、署名アルゴリズムは同じだが、↑のPublic nonce Rの部分の計算にdへのコミットメントを含める。具体的には、以下のようにPublic nonceの計算を変える↓
- nonce kを選択(xとmを使ってRFC 6979で決定論的に生成される)
- R = kGを計算
- e = k + H(R || d)を計算
- Q = R + H(R || d)Gを計算
- q = Q.x mod nを計算
- を計算
- (q, s)がECDSA署名データ
Public nonceとして単純にRを使うのではなく、RにH(R || d)Gを加算した値QをPublic nonceとしている。Pay to contractでは受信アドレスに適用していた計算を、署名のPublic nonceに適用したものになる。
単純にdGをそのままPublic nonceとしないのは、dを開示すると、署名データとdから秘密鍵xの値が逆算できてしまうため。そのためR = kGを加算することで、dを開示しても秘密鍵の逆算をできないようにしている。
このように署名データにコミットメントスキームを組み込むことで、たとえコミットメントデータ(d)が失われたとしても、コミットメントが消失するだけで、Pay to contractの課題であったような資金の消失に繋がることはない。