暗号通貨に関する事など

暗号通貨に関する覚書など。メモや日記。

※技術的なことに関して、間違っていたらコメントから指摘していただけると泣いて喜びます

Segwitに関して調べた記録5


前回の続き



はじめに

 この記事ではSegwitによって新たに採用されるトランザクション署名用メッセージのシリアライズ方法について書くが、ここで一点前置きをしておきたい。


 Bitcoinの署名用メッセージの生成方法は、予めいくつかの決められたパターンが存在し、そのパターンはHashTypeと呼ばれる。このHashTypeは署名データの一番後ろに1byteで表現されて付け加えられ、unlock scriptに入れられる。
(詳しい仕組みは下記BitcoinWikiのOP_CHECKSIGの項目で確認してください)

OP_CHECKSIG - Bitcoin Wiki


 このHashTypeはSegwitでの署名検証においても使用されるので、本来であれば、それぞれパターンに分けて説明をするべきなのだが、ここでは簡単に説明するため、一般的に使われる「SIGHASH_ALL(=0x01)」に関するシリアライズに絞って書く。



レガシーな署名用メッセージのシリアライズ (SIGHASH_ALL)

 Segwitで使われる署名用メッセージのシリアライズ方法を書く前に、通常のP2PKHなどで使用されるレガシーな署名用メッセージのシリアライズ方法に関して書いておく。


 Segwit採用前のトランザクション署名用メッセージのシリアライズ(SIGHASH_ALL)の方法はunlock scriptフィールドが空の状態のトランザクションに、lock scriptを差し込んだものと、Hasyを4byteで表現したデータを合わせてHash256(SHA-256doubleHash)して生成している。


※新たに発行するトランザクションに参照しているロックスクリプトを差し込む際に、script内に
 OP_CODESEPARATORがあるときは注意が必要。



 ここで、署名用メッセージとしてシリアライズされるフィールドというのはつまり「署名によって守られているフィールド」を意味している。



BIP-143で定められている新しいシリアライズ (SIGHASH_ALL)

 では、BIP-143で定められている新しい署名証メッセージ(SIGHASH_ALL)はどうやって生成するのか、BIP-143を引用すると下記のとおりとなっている。

Double SHA256 of the serialization of:

 1. nVersion of the transaction (4-byte little endian)

 2. hashPrevouts (32-byte hash)

 3. hashSequence (32-byte hash)

 4. outpoint (32-byte hash + 4-byte little endian)

 5. scriptCode of the input (serialized as scripts inside CTxOuts)

 6. value of the output spent by this input (8-byte little endian)

 7. nSequence of the input (4-byte little endian)

 8. hashOutputs (32-byte hash)

 9. nLocktime of the transaction (4-byte little endian)

 10. sighash type of the signature (4-byte little endian)


BIP-143より引用

https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki

 1、4、7、9、10に関しては、レガシーなシリアライズと同じ、新規発行した署名前のトランザクションのフィールドから取り出した値を使用すれば良い。それ以外の2、3、5、6、8に関して、一つずつ見ていこう。



2. hashPrevouts (SIGHASH_ALL)

 hashPrevoutsは新規発行TxのTx_Inの中にある全てのoutPointフィールドを取り出して(index順に)繋げたものにHash256を行う。


3. hashSequence (SIGHASH_ALL)

 hashPrevoutsは新規発行TxのTx_Inの中にある全てのsequenceフィールドを取り出して(index順に)繋げたものにHash256を行う。


5. scriptCode of the input  (SIGHASH_ALL)

 これから署名を行おうとするTx_inが参照しているlock scriptについて…


■P2WPKHの場合

0x 19 76 a9 14 {20-byte-pubkey-hash} 88 ac

 となる。(lockscriptに格納されている状態から、Bitcoin scriptの処理に変換して使用する)


■P2WSHの場合
 witness scriptにOP_CODESEPARATORが含まれていない場合は、witness scriptをそのまま使用する。OP_CODESEPARATORが含まれている場合は、witness scriptにあるOP_CODESEPARATORのうち、一番最後のもの以降のwitness script部分を使用する。


6. value of the output spent by this input  (SIGHASH_ALL)

 これから署名を行おうとするTx_inのoutPointにて参照しているTx_outのvalueフィールド
(つまりこのTx_inが解錠するBitcoinの量)


8. hashOutputs  (SIGHASH_ALL)

 新規発行トランザクションのTx_out部分をindex順に全てシリアライズしてつなげたデータにHash256を行う。


署名によって守られる要素 (SIGHASH_ALL)

 以上の手続きでシリアライズしたデータに署名を行うということはつまり、署名によってそれらが守られることを意味する。新しいシリアライズによって守られるTxの部分を図で示す。
(着色部分は署名によって守られる)

 BIP-143のシリアライズによって新たに加わったところとしては、参照先のTx_outのvalueフィールドが保護されるようになったところである。また、その他の特徴としては、フィールドをそのまま使用するのではなく、トランザクションを構成する要素になる各フィールドを繋げてHash256したダイジェストを使用するところだ。



BIP-143で定められている新しいシリアライズ (さいごに)

 BIP-143で定められている新しいシリアライズ(SIGHASH_ALL)に関する説明は以上となる。この辺りの話を実際に理解するには、実際に自分でシリアライズしてみて検証してみたほうが良いと思う。


 幸い、BIP-143にはいくつかサンプルが載っているので、それと照合して確認するのが良い方法だと思う。


〜6に続く〜

仮想通貨NEM NanoWalletの基本操作

はじめに

 NanoWalletの基本的な使い方に関する質問のうちmijinフォーラムに質問が多い部分を中心に、簡単に説明していきます。(特に質問としてよく見かける部分のみ)



ホーム画面での操作

 特に書くこともないので画像をもって説明とします。NanoWalletは精力的にアップデートがされており、それらのアップデートはユーザーの為にされているアップデートなので、バージョンは常に最新のものを使用しましょう。最新バージョンの確認はNEMの公式サイトで。



3種類のウォレット作成画面

 NanoWalletを初めて使うとき、また、モバイルウォレットやNCCなどからウォレットを移植するときに遭遇するウォレット作成画面ですが、NanoWalletには3種類のウォレット作成法があるので、それぞれ説明していきます。


■シンプルウォレット

 初めてウォレットを作成するときはこのシンプルウォレットで良いでしょう。但し、このシンプルウォレットで生成される秘密鍵はNCCで生成されるものよりセキュリティのレベルが低い危険性があります。技術的な説明は省きますが、その旨画面にもしっかりと注意書きが書かれています。
(この画面に限らず、画面に表示される注意書きは必ず読みましょう)



■ブレインウォレット

 シンプルウォレットと似たようなものかと考えてしまいますが、ブレインウォレットを使用するときは特別な注意が必要です。


 ブレインウォレットのパスフレーズは、シンプルウォレットのパスワードと違い、パスフレーズそのものが秘密鍵と直接結びつきます。そのため、注意書きにもありますが使用するときはとにかく長く(最低40文字以上)、できるだけランダムなパスフレーズを使用しましょう。
 このパスフレーズが盗まれることは資産が盗まれることを意味します。


 個人的にですが、私はあまりブレインウォレットを使用することはないです。



■プライベートキーウォレット

 プライベートキーウォレットは秘密鍵を指定してウォレットを作成することが出来ます。


 主にモバイルウォレットを移植したり、NCCで生成したウォレットの秘密鍵を直接使用してウォレットを移植するときに使用される機能だと考えてよいです。



■結局、どれを使えばよいのか
 取引所での保管をやめて、初めてNEMのウォレットとして使用したい時にはシンプルウォレットを、他のウォレットから移植したい時にはプライベートキーウォレットを使用すると良いでしょう。


 もちろんブレインウォレットを使用しても構いません。ランダムな、とても長いパスフレーズを使用した場合、そのブレインウォレットはセキュリティ的に優れているものとなるでしょう。
(ログインする時にパスフレーズを全て打ち込むので、ログインが大変にはなりますが・・・)



ウォレット作成画面で出てくる注意書き

 ウォレットを作成するとき、上記のような注意書きが表示されると思います。この注意書きは途中書いてあることがわからなかったとしても必ず一度全て目を通しましょう。


 この画面になると、何かのファイルがダウンロードされると思います(拡張子がwltのファイル)。そのファイルはウォレットファイルのバックアップになるので、安全な場所に保管しておきましょう。


 また、秘密鍵を表示してそれをオフラインの環境(紙に書く、画面をデジカメで撮る、クリプトスティールにセットするなど)で安全に保管することも忘れずに行ってください。



結局のところ、何を保管しなくてはならないのか

 NanoWalletで資産を保管する上でバックアップを取らなくてはならないものは主に3つです。

  1. 秘密鍵 (最重要。必ずオフラインで保管すること)
  2. パスワードまたはパスフレーズ (同じく最重要。必ずオフラインで保管すること)
  3. ウォレットファイル:拡張子wlt (バックアップは複数箇所に分散して保管することを推奨)



ダッシュボードでまず最初に確認すべきこと

 さて、ウォレットを生成してログインするといよいよNanoWalletを使用することが出来るようになるわけですが、ここで確認すべきことがあります。


 画面右上の「ノード」の部分を見てください。この部分が上記図のように赤い丸となっているとき、あなたのNanoWalletはNISサーバーと正常に通信ができていない状態になっています。


 これは「ノード」部をクリックした後、上記図のように接続先のノードを変更すれば良いだけなので、赤い丸が緑の丸になるノードを探して接続先を変えましょう。



ウォレットバックアップデータの出力

 ウォレット生成時にウォレットのバックアップファイルを保管することになると思いますが、万が一消してしまったときなどに、再度バックアップファイルを出力するには、上記図の赤枠の場所を操作してバックアップファイルを出力することが来ます。


 また、秘密鍵の出力、モバイルウォレット移植用のQRコードの出力なども、この画面で出来ます。



困ったことがあったら

 mijinフォーラムを検索しましょう。調べてなければ、mijinフォーラムで聞きましょう。多くの場合、誰かが答えてくれると思います。



最後に

 NanoWalletの基本的な操作のうち、送金などを飛ばしてmijinフォーラムなどでよく質問として出てくる部分を抜粋して説明しています。分からないことがあれば根気よく調べ、それでもわからなければフォーラムで聞きましょう。


 また、基本的な心構えとして、仮想通貨は自己の責任において管理されるものです。例えばあなたが間違ったアドレスに資産を送ってしまった場合、それを取り返すのは極めて困難(事実上不可能だと考えて良い)です。
 そのため、ウォレットの使い方もそうですが、何よりまず最初に最悪無くなっても良い金額でテストして、仕組みを理解してから実際に使用することを強くおすすめします。

Segwitに関して調べた記録4


前回の続き



Witnessと署名検証に関して

 Segwit(BIP141-BIP145)で新たに導入されるWitnessという構造は、それ以前のBitcoinscriptとは異なる部分が多い。


 例えば、Witnessは今までのBitcoinscriptのように、OpCodeを淡々と処理した結果がtrueであれば署名を正当なものと判断するのではなく、検知した“バージョン”毎に決められた処理を行い、その結果を署名検証の結果とする。


 また、OP_CHECKSIGを行うときなどに使用される署名用のメッセージ(SHA-256doubleHashされる前のデータ)も、今までのように署名前のTxにLockscriptを差し込んだものを使用するのではなく、新しく決められたルールによってシリアライズされたデータを用いる。
(シリアライズは今まで通りHashTypeによってそのルールが異なるが、このブログでは一般的に使われるSIG HASH ALLのみに関して書く)



バージョン0のWitnessProgramとLockscript

 ここではまず、WitnessProgramが何をもって「このLockscriptはWitnessProgramだ」と判断するのか、ということについて書く。


 Segwit後もLockscriptはそれまでと同じようにTx-outのLockscriptフィールドに入れられ、署名検証を行うとき、適宜WItnessProgramか、レガシーなBitcoinscriptかを判断してそれらにあった方法で署名検証が行われる。


 現在はバージョン0のWitnessProgram(P2WPKH,P2WSHの二種類)のみが定められており、下記条件をWitnessProgramのトリガーとしている。


■version0のP2WPKH

  1. Lockscriptが"0"から始まる(この0をバージョンバイトと呼ぶ)
  2. 1byteのバージョンバイト(0x00)に続き、20byteのデータプッシュが続く
  3. 対応するTx-inのunLockscriptが空の状態である


 ここで注意が必要なのは、P2WPKHに使用する公開鍵は圧縮形式の公開鍵でないと受け付けられないという点だ。


■version0のP2WSH

  1. Lockscriptが"0"から始まる
  2. 1byteのバージョンバイト(0x00)に続き、32byteのデータプッシュが続く
  3. 対応するTx-inのunLockscriptが空の状態である



 バージョンバイト(0x00)に続くデータはP2WPKHの場合は圧縮された公開鍵(先頭が0x02または0x03で始まる公開鍵)をHash160(SHA-256_RIPEMD-160)したものであり、P2WSHの場合はredeem-scriptをHash256(SHA-256doubleHash)したデータである。


 上記の他に、既存のP2SHでネストさせる方法とそのトリガーもあるが、ここでは紹介しない。簡単に言うと、LockscriptがP2SHで、redeem-scriptにP2WPKHやP2WSHを閉じ込めることも可能であるということだ。


 Segwitに対応したノード、クライアントは上記フォーマットのLockscriptを検知すると、Witness用の署名・検証に処理を移す。



署名検証

 では実際、P2WPKHやP2WSHをノードやクライアントが検知した場合、どういった署名検証の処理を行うのか。

 バージョン0で定められているP2WPKHとP2WSHの処理の内容は実際のところ、それまでのP2PKHやP2SHと変わらない。例えばP2WPKHの場合、Witnessに [signature] [publickey] の順にデータが格納され、検証の際にはpublickeyHashをP2WPKHに格納されたそれと照らし合わせ、一致すれば [signature] [publickey] をECDSA検証器にかける。

(流れはP2PKHの OP_DUP ... OP_CHECKSIG と同じ流れ)



未知のバージョンを検知した時

 現在バージョン0のみが定められているという話をしたが、例えば未知のバージョンが検知された時、WitnessProgramはどういった動きをするか。


 結論から言うと、未知のバージョンを検知した時WitnessProgramはそのLockscriptをANYONE_CAN_PAY(誰でも使用することが出来るTx-out)として処理を行う。つまり、誰が使用したとしても署名検証を通す。


 なぜこんなことをするのか、それは将来新しいバージョンのWitnessProgramをフォークして追加した時に、後方互換を意識しなくて済むようにするためだ。新しいプログラムを追加した際、古いノードがネットワークに紛れていても、そのノードはそのTx-outをANYONE_CAN_PAYとして取り扱うので、特別な後方互換手段を用意する必要がなくなる。




次に署名用メッセージのシリアライズの話に移りたいが、長くなってしまうのでここで一旦区切る。
〜5に続く〜