Develop with pleasure!

福岡でCloudとかBlockchainとか。

Bitcoin Core 0.13.2のリリース

先日Bitcoin Core 0.13.2がリリースされた↓

bitcoincore.org

リリースノートは↓

bitcoincore.org

主な変更点

0.13系のマイナーアップデートなので、基本的にはBugfixとパフォーマンス改善のリリースになるので、新機能のリリースは無い。

古いOSをサポート対象外に

0.13.2というよりは0.13.x系だけど。

Windows

Windows XP自体が既にMicrosoftのサポートも切れ、セキュリティアップデートも提供されておらず、Bitcoin Coreも0.12.xでランダムにクラッシュする報告が挙げられているが、QtなどのライブラリがもうXPでテストされていない可能性もあり、サポートに割く時間もリソースも無いので、0.13.0以降、Windows XPはサポートしない。

Mac OS

0.13.1からOS X 10.7はサポート外に。0.13.1以降はOS X 10.8以降のみをサポート。

ウォレットのmempoolのリジェクトのハンドリング方法の変更

新しく作成したトランザクションが、制限によりmempoolに入れることが出来なかった場合、今までの仕様では、そのトランザクションをブロードキャストしようとしたRPCコールはエラーを返し、そのトランザクション自体はウォレット内に入っており、いくつかのトランザクションが承認されるとソフトウェアの再起動後にブロードキャストされる。

0.13.2では、↑のRPCコールは成功を返し、トランザクションの再ブロードキャストと同時にmempoolへの挿入を再試行するよう変更され、ソフトウェアの再起動を回避するようになった。

mempoolに格納されていないウォレット内のトランザクションは、abandontransaction RPCを使って放棄できる。

Teechanの決済プロトコル

Bitcoin-NGやCovenantsなどの提案をしているコーネル大学の先生方が先日Teechanというオフチェーン決済のプロトコルに関するブログとホワイトペーパーを公開していたので見てみる↓

hackingdistributed.com

https://www.cs.cornell.edu/People/egs/papers/teechan.pdf

TeechanはTrusted Execution Environment(TEE)を利用したPayment Channelの実装プロトコルで、TEEを備えた2つのエンドポイント間にPayment Channelを構築する。

Trusted Execution Environment(TEE)とは

TEE=信頼できる実行環境で、ホワイトペーパーの中ではCPUの拡張命令セットの1つであるSoftware Guard Extensions(SGX)を利用している。SGXはアプリケーションがシステムメモリ上に保護された領域を作成できる仕組み(その他のプログラムはアクセスできない)で、重要なデータをマルウェアなどから守ることを目的に最近のCPUに追加された命令セットになる。

チップにはEnclaveと呼ばれる特別な構成があり、Enclave内のメモリデータは、オフチップでは必ず暗号化されており、特殊なEnclaveコードが実行されている間のみオンチップでのみアクセスできる。
さらに復号化キー特定のハッシュを持つコードのみに有効であるため、もし攻撃者がEnclaveをハックしてそのハッシュを書き換えるても、ハッキングされたコードは暗号化キーにアクセスできなくなるため攻撃は成功しない。そのためコードの内容を自由に書き換え可能なマシンの所有者であっても、Enclaveの内容を覗いたり実行コードを変更することはできない。

またSGXハードウェアは特定のEnclaveが特定のソフトウェアディストリビューションを実行していることをリモートコンピュータに証明する機能を持つ。つまり、そのチップは”特定のハッシュを持つコードを実行していることをリモートパーティに保証する”ことができ、これがPayment Channelを構築する上で重要なファクターになっている。

SGXの詳細については、IntelのSGXの説明のホワイトペーパー参照↓

https://eprint.iacr.org/2016/086.pdf

TEEを利用するTeechanはSegwitが無くても双方向のPayment Channelを構築でき、1取引で複数回のメッセージ往復が必要なLNと違い、1つの取引は片方から1つのメッセージを送るだけで完了するというシンプルさがある。

Teechanの決済プロセス

ホワイトペーパーの4章にTeechanの具体的な決済プロセスが記述されている。

Teechanチャネルプロトコルは3つのフェーズからなる。

  1. チャネルの確立
  2. チャネル操作
  3. チャネルの決済

↓で、これらの3つフェーズのそれぞれで交換されるメッセージを詳細に示している。

f:id:techmedia-think:20161224151458p:plain

チャネルの確立

最初のフェーズでは、アリスとボブの間で双方向のPayment Channelを確立する。今までのPayment Channelと同様、セットアップと払い戻し用のトランザクションを使ってPayment Channelを確立する。アリスとボブは2-of-2のマルチシグにBitcoinデポジットするセットアップトランザクションを構築する。
続いてセットアップトランザクションを入力にし、アリスとボブの資金を返却する払い戻しトランザクションを構築する。払い戻しトランザクションにはロックタイムが設けられていて、将来のある時点になると利用可能になる。必ずこのロックタイムの時間より前にチャネルを閉じる必要がある。

A1

最初にアリスとボブはそれぞれのEnclaveをセットし、セットアップ及び払い戻しトランザクションを構築する。この時必要になるのが

A2

続いて、Enclave AとEnclave Bはセキュアな通信チャネルを確立し、remote attestationを通じてお互いを認証する。この時、各Enclaveは安全な乱数生成器を使って、非対称暗号の鍵ペアとランダムな秘密鍵を生成する。
アリスのEnclaveは生成した非対称公開鍵(KA)をSGXのQUOTEにバインドし、ボブに送信する。ボブは、KAで暗号化したデータはアリスのEnclaveによってのみ復号化され、Enclaveが必要なバイナリハッシュを持つEnclaveコードを実行していることを検証する。
同じことを逆方向でも行い、アリスのEnclaveもボブの公開鍵を取得する。相互検証が成功すると、Enclave AとEnclave Bははそれぞれ、KAKBで暗号化されたデータが相手のEnclaveでのみ復号化できる状態になり、秘匿通信チャネルを確立したことになる。

A3

ボブのEnclaveはステップA1のボブのセットアップデータ(kBTC,BUTXOBBTCB)と一緒にランダムな秘密鍵IDBをアリスのEnclaveに提示する。アリスのEnclaveは内部的に署名付きのセットアップ及び払い戻しトランザクションを生成し、セットアップトランザクションのハッシュ(SetupHash)と払い戻しトランザクションをアリスに明かす。この時点ではアリスのEnclaveだけがセットアップトランザクションを知っている。

続いて、アリスのEnclaveはA1のアリスのセットアップデータ(kBTC,AUTXOABTCA)と一緒にランダムな秘密鍵IDAをボブのEnclaveに提示する。ボブのEnclaveは内部的にセットアップトランザクションと払い戻しトランザクションを生成し、その両方をボブに明かす。ボブはセットアップトランザクションBitcoinネットワークにブロードキャストし、チャネルを確立する。
アリスはブロックチェーン上にSetupHashと同じTXIDのトランザクションを見つけることでチャネルの確立を検知する。

以上のステップのハンドシェイクが終わると2つのEnclave間の安全な通信チャネルが確立する。

チャネル操作

Enclave AとEnclave Bの間でチャネルが確立すると、アリスとボブは資金の交換をスタートできる。この段階ではアリスもボブもBitcoinネットワークとの接続を維持する必要は無い。

B1

ボブに資金を送るため、アリスはボブに送りたい資金の量を指定して自分のEnclaveにローカルでリクエストを送る(A1)。

B2

Enclaveはオーナー(アリス)から支払いのリクエストを受信すると、送ろうとしている量が残高内かチェックする。問題なければ残高を更新し、支払いを承認するメッセージを作成する。このメッセージには、支払いを行うEnclaveのランダムな秘密鍵IDAと、更新された支払いカウンタ(初回は1)が含まれる。メッセージは非対称公開鍵KBで暗号化され、ボブに送られる。

B3

ボブはメッセージを受信するとそれをボブのEnclaveに送る。Enclaveがメッセージを受信すると、メッセージを復号化し、正しい秘密鍵かどうかとカウンタが以前提示されたものより1つ大きいものかチェックする。問題なければ残高とカウンタを更新し、ボブに残高を通知する。

B1〜B3のステップが1つのオフチェーン決済となり、決済の都度このステップを繰り返す。

チャネルの決済

Teechanプロトコルの最終段階はチャネルの決済である。このフェーズでは、Payment Channelが閉じられ、アリスとボブ間の最終的な残高を決済するトランザクションBitcoinネットワークにブロードキャストされる。

C1

フェーズ2のいずれかの時点で、両者のいずれかがEnclaveに対して終了リクエストを送信する。

C2

Enclaveはオーナーから終了リクエストを受信すると、セットアップトランザクションでロックされた資金を現在の残高に応じてアリス、ボブそれぞれに送る決済トランザクションを生成し、kBTC,AkBTC,Bを使って署名する。このトランザクションはホストに返されEnclave内のメモリデータは全て破棄され、実行を停止する。

C3

Enclaveから決済トランザクションを受け取ったオーナーはそれをBitcoinネットワークにブロードキャストして決済を完了する。

まとめ&所感

  • TeechanではTEEを信頼できるサードパーティとして利用していて、両者のEnclaveが信頼できるサードパーティとして機能する前提で、お互いの秘密鍵を相手のEnclaveに送っている。
  • 両者のEnclaveが相手の秘密鍵も持っているので、オフチェーンでの決済は残高が合意できれば、Enclave内に相手の鍵と自分の鍵があるので、いつでもそれでトランザクションを作って署名できる(その操作を行うのは全てTEEデバイス)。
  • トラストポイントを排除してきた既存のPayment Channelと違いEnclave等のTEEをを使ったトラストポイントを利用することで、作成するトランザクションはシンプルで、二者間のメッセージ交換の手間も省いている。
  • LNだと両者間でシークレットから生成したハッシュの交換や鏡像となるトランザクションの交換など1つの取引で複数のメッセージ交換を必要とするのに比べ、1つの取引が1回のメッセージで完了するというのはシンプルで良い。
  • 今までのマイクロペイメントチャネルだと、トラストポイントが無い形で自分のコインを保護できるが、そのためにはBitcoinネットワークを監視し相手が不正していないか検知する必要があったが、そういった監視をする必要が無くなる。
  • TEEを使ったPayment Channelを構成する上で重要なのが、SGXのremote attestation機能だけど、これ現状でどれくらい使えるものなのか気になる。
  • 故障なんかでenclaveのデータが読めなくなった場合ってどうなるのかね?
  • あとEnclave間のリモート通信がどういうネットワークプロトコルで行われるのか気になる。

Federated Pegのアドレス導出スキーム

Blockstreamが公開しているSidechainのホワイトペーパーのAppendixにFederated Pegを行う際のP2SHアドレスの導出スキームが定義されている。このFederated Pegの仕組みは同じくBlockstreamが公開しているサイドチェーンの実装Elements Alphaでも利用されている。

techmedia-think.hatenablog.com

楕円曲線の準同型性を利用したこのアドレス導出のスキームの実装がどうなってるのか見てみる。

Federated Pegのコンセプト

現在のBitcoinスクリプトにはSPV proof検証が行えるような機能は無いため、Bitcoinとサイドチェーンをペグする方法としてはFederated Pegを利用する方法がとられている。OP_SIDECHAINPROOFVERIFYのようなソフトフォークも考えられているみたいだけど、最近のSegwitのデプロイ状況を見てもわかるようにソフトフォークといっても合意を取るのは難しいので、ソフトフォーク無しでペグするのが現状は妥当なアプローチだと思う。

Federated Pegでは、信頼できる連合の職員にスクリプトを評価させることで、Bitcoinスクリプトを拡張して実現しようとしていた機能を外部的に実装している。そのため連合の職員というトラスポイントが発生する。

ホワイトペーパーに記載されている例より

連合職員5人の内3人の署名が必要なケースを考えた場合、連合はsecp256k1の楕円曲線上の点(公開鍵)P1、P2、P3、P4、P5と、redeemscriptのテンプレート3 x x x x x 5 OP_CHECKMULTISIGを持ち、それらはサイドチェーンの全参加者に知られている。ユーザはfederated pegを使ってサイドチェーン上でコインを有効にするため、以下のスキームでクロスチェーンP2SHアドレスを導出する。

f:id:techmedia-think:20161218161811p:plain

この導出スキームはBIP-32で使われているのと同じ準同型の手法をベースにしていて、第三者がリンク不可能なアドレスを生成でき、pay-to-contractトランザクションと同じ構成でもある。

アドレスを生成すると、そのアドレス宛てにコインを送る。コインを送ったユーザは連合の職員にnonceとscriptPubkey、SPV proofに提供すると(職員がBitcoinのブロックチェーン上の支払いを確認するのに必要)、送ったコインと同額のコインをサイドチェーン上で入手することができる。Bitcoinとサイドチェーン間のコインの転送は、標準のP2SHアドレスへ支払い、任意のScriptPubKeyに対して支払われるので、マルチシグアドレスをサポートしているBitcoinサービスであればすぐにでもfederated pegを利用してサイドチェーンへのコインの支払い、サイドチェーンからのコインの受取ができる。

federated pegのアプローチではチェーン間の移動の際に連合の職員というトラストポイントが発生するが、Bitcoinになんら変更を加える必要がないのと、サイドチェーンの利用を限られたユーザのみにしぼりたい場合も、連合の職員によってそういった制御をすることが可能になるといったメリットもある。

実装

実はこれをRubyで実装したものがbitcoin-rubyの一部にある↓

https://github.com/lian/bitcoin-ruby/blob/master/lib/bitcoin/contracthash.rb

ので、身近なRubyの実装でみていく。

アドレスの導出

コインをBitcoinからサイドチェーンに送る際のP2SHアドレスを計算する。

bitcoin-rubyでこれを実装しているのがBitcoin::ContractHash#generate

引数に渡すのが↓の3つ

  • redeem_script_template
    redeemscriptのテンプレートで↑のホワイトペーパーでは、3 x x x x x 5 OP_CHECKMULTISIGの部分。
  • payee_address
    サイドチェーン上でコインを受け取るアドレス(ホワイトペーパーではScriptPubKey)
  • nonce_hex
    128bitの乱数

この実装が↑のホワイトペーパーに記載されているアドレス導出スキームの実装にあたり、以下のプロセスでP2SHアドレスを生成している。

  1. noncepayee_addressを組み合わせてdataを生成する
  2. redeem_script_template3 x x x x x 5 OP_CHECKMULTISIG)のマルチシグの各公開鍵=楕円曲線上の点に対して、1で生成したdataを加算して新しい点=公開鍵を生成する。
  3. redeem_script_templateの各公開鍵の部分を、2で生成した新しい公開鍵に置き換えたP2SHスクリプトを生成する。
  4. 3で生成したP2SHスクリプトから生成したP2SHアドレスとそのredeem_scriptnonceを返す。

ユーザは生成されたP2SHアドレスにコインを送付する。

連合の職員の秘密鍵

ユーザーは職員にpayee_address(ホワイトペーパーではScriptPubKey)とnonceを渡す。連合の職員は渡されたpayee_addressnonceを使って秘密鍵を入手する。

この処理を実装しているのがBitcoin::ContractHash#claimで、

引数に渡すのが↓の3つ

  • private_key
    元々公開していた公開鍵の秘密鍵
  • payee_address
    ユーザから渡された支払先のアドレス(ホワイトペーパーではScriptPubKey)
  • nonce
    ユーザから渡されたnonce

↑でユーザがコインを送付したアドレスのロックを解除するための秘密鍵を↑のclaimメソッドで生成している。ユーザから渡されたpayee_addressnonceから元々の公開鍵に加算されたdataを計算し、秘密鍵にそのdataを加算した新しい秘密鍵を生成している。

ポイントとなるのは、ユーザは公開されている職員の公開鍵に対してnonceとアドレスから生成したdataを加算した公開鍵を生成しており、職員はそれに対応する秘密鍵を同じく秘密鍵dadtaを加算して入手してる点で楕円曲線の準同型性を利用している。ユーザがコインを送付するマルチシグは連合のマルチシグの各公開鍵にデータを加算したマルチシグであるため、このアドレスへの支払いがサイドチェーンへの支払いになっていることを第三者がリンクすることはできない。

楕円曲線を使ったゼロ知識証明

↓のゼロ知識証明の解説記事に掲載されている楕円曲線を使ったゼロ知識証明をbitcoin-rubyを使って検証してみた。

www.atmarkit.co.jp

検証手順は↑のの記事の通りで、

証明者(アリス)と検証者がいて、楕円曲線上の点Pとアリスの秘密鍵aがあるとき、その公開鍵は

Q(公開鍵) = aP

となり、PQは検証者に共有されている。この状況でアリスは確実に秘密鍵aを持っていることをaを開示することなく、検証者に証明する。

まず、アリスはランダムな値rを選択肢、 R = rPb = H(P, Q, R)を計算する。Hはハッシュ関数で、今回はBitcoinハッシュ関数hash160を使用。
続いてc = r + abを計算し、検証者に(R, c)を渡す。

検証者は共有された値PQRcを使ってアリスがaを持っていることを確認する。
確認方法b = H(P, Q, R)X = cPY = R + bQを計算し、XYが等しければアリスはaを持っていると判断する。

どうしてXYが等しければアリスはaを知っていると判断できるのかというと、X = cP = (r + ab)Pは、秘密鍵abを乗算し、ランダムに選択した秘密鍵rを加算した値になる。そしてYは公開鍵Qbを乗算し、秘密鍵rの公開鍵Rを乗算した値になる。秘密鍵に対してrを加算した場合、その楕円曲線上の点は公開鍵QRを加算したものと等しくなるという楕円曲線の特性と、仮にaを知らない場合その計算式が成り立つようなRや(ハッシュ関数によって生成された)cをアリスが導出することは非常に難しいことから、X = Yが等しい場合アリスはaを知っていると判断することができる。

検証コードは↓

Rubyで楕円曲線の鍵共有(ECDH)と加算

Bitcoinで使われる楕円曲線の鍵について、bitcoin-rubyを使って鍵交換(ECDH)と楕円曲線の加算をしてみる。

鍵共有(ECDH)

アリスとボブが持つ鍵を使って共通鍵を生成してみる。

アリスとボブはそれぞれお互いの公開鍵を知っており、秘密鍵をそれぞれab楕円曲線のベースポイントPとすると、

アリスの公開鍵は、

Q(a) = a*P

ボブの公開鍵は

Q(b) = b*P

となる。

この前提でアリスとボブがお互いに相手の公開鍵を自分の秘密鍵を使ってスカラー倍算する。

アリスは

a * Q(b) = ab*P

ボブは、

b * Q(a) = ba*P

楕円曲線上でab*P=ba*Pとなるため、お互いが計算した値は同じ点を指す。この時アリスはaをボブはbを相手に公開していないので、安全に共通鍵を生成できる。

この楕円曲線を使ったDH鍵共有をbitcoin-rubyを使って書くと↓のようになる。

実際の鍵共有はffiでOpenSSLの機能を使っており、dh_compute_keyの中身はOpenSSLのC実装になる。

楕円曲線の加算

Bitcoinの取引の量を秘匿するConfidential Transactionや、Pay-to-Contractプロトコルなど楕円曲線の加法特性を利用した暗号トリックを使うケースが増えており、そんな楕円曲線の加算を行うRubyのコードを書いてみる。

アリスのBitcoinの公開鍵と秘密鍵に対して、ランダムに選択した値rを別々に加算する。公開鍵にr加算してできた公開鍵と、秘密鍵rを加算してできた秘密鍵から生成した公開鍵が同じ値になることが確認できる↓

こちらの楕円曲線の加算の実装もOpenSSLを利用。

ECDHも加算も楕円曲線の演算は全てOpenSSL側で実装されているので、Rubyはあくまでラッパーかな。Secp256k1を使った実装もあるけど、そっちも実装はlibsecp256k1なので、いずれにせよPure Rubyの実装があるわけではない。