用語集 / 開発者向けリファレンス
OP_HASH160
- OP_HASH160とは?
- OP_HASH160はスタックの最上位の項目にSHA-256を適用し、その結果にRIPEMD-160を適用して、20バイトのダイジェストを残します。これは、1または3で始まるすべてのアドレスに含まれる同じ指紋です。
1バイトの0xa9が、暗号学で最も研究されてきた2つのハッシュ関数の代わりを務めています。この組み合わせにより、32バイトの出力が20バイトに縮小され、どちらかのアルゴリズムの弱点に対する保険になりますが、その代償として衝突耐性は128ビットではなく約80ビットになります。ビットコインのアドレスが電話口で読み上げられるほど短いのは、このためです。
仕組み
OP_HASH160は任意の長さの項目を1つポップし、ちょうど20バイトをプッシュします。同じ入力からは常に同じダイジェストが生成されます。
この2つの関数は、互いに関係のない設計の系譜に由来します。RIPEMD-160は、公開の場で活動する欧州の学術チームによって1996年に発表されました。SHA-256はNSAから生まれ、2001年にNISTによって標準化されました。両者を連鎖させるのは保守的な選択でした。一方に構造的な破綻が生じても、攻撃者と有用な偽造の間にはもう一方が依然として立ちはだかり、30年の間に、この構造を脅かす形で破られたものはどちらもありません。
サイズの削減は見た目だけの話ではありません。恒久的なグローバル台帳を小さく保つことが目的だった当時、出力ごとに12バイトを節約することは重要であり、古典的なロックスクリプトが37バイトではなく25バイトであるのはそのためです。
ただし、20バイトには限界があります。160ビットのダイジェストを共有する2つの入力を見つけるには、2の128乗ではなく2の80乗程度の演算が必要です。ハッシュ化する鍵を自分だけが選ぶ場合は問題ありませんが、取引相手がコミットするスクリプトの選択に関与する場合は、はるかに心もとなくなります。まさにこの理由から、分離ウィットネス(SegWit)はP2WSHでスクリプトのコミットメントを単一の32バイトのSHA-256に移し、単一鍵の出力には短い形式を残しました。
どこで見られるか
OP_HASH160は2つのスクリプトテンプレートに存在し、その出力は、これまでにコピーしたほとんどすべてのアドレスの中に含まれています。
レガシー出力では公開鍵に対して実行されます。Pay-to-script-hash出力ではredeem scriptに対して実行されます。どちらの場合も、目にするアドレスは、先頭にバージョンバイト(1で始まるアドレスには0x00、3で始まるアドレスには0x05)を付けたその20バイトのダイジェストをBase58Checkのチェックサムで包んだものです。ネイティブSegWitの単一鍵出力は、同じ20バイトをオペコードをまったく含まずに保持します。その出力タイプのルールはスクリプトとして書かれるのではなく、バリデータに組み込まれているからです。
Taprootはこの慣習を打ち破りました。bc1pの出力は、間にハッシュ化のステップを挟まずに32バイトの公開鍵にコミットするため、Taprootのアドレスにはhash160がどこにも含まれません。
ハードウェアウォレットの画面でアドレスを確認することが実際に機能する理由もここにあります。どこか1か所でも異なる2つのアドレスは、互いに関係のない2つのダイジェストを生成するため、すり替えられたアドレスがほとんど正しいように見えることはありません。デバイス上の先頭と末尾の数文字をコンピューターに表示されたものと比較するだけで、クリップボードマルウェアを捕捉できます。
OP_HASH160 vs SHA-256
SHA-256はハッシュ関数であり、OP_HASH160はたまたまそれを1回呼び出す命令です。この関数はスクリプトを介さずにビットコインの至る所に現れます。プルーフ・オブ・ワークはブロックヘッダーをそれで2回ハッシュ化し、トランザクション識別子はその二重適用であり、マークルツリーもそれで構築されます。このオペコードはBitcoin Scriptの中にのみ存在し、出力が使用される間だけ実行され、常に32バイトではなく20バイトを生成します。それが行う構成、すなわちSHA-256の出力にRIPEMD-160を適用する処理は、ウォレットのコードで独自の名前hash160を持つほど一般的であり、ライブラリの関数一覧を読む際には認識しておく価値があります。