3章_アドレス
概要
クッキートークン(CT)の取引・管理にあたって、個人名の代わりに「公開鍵ハッシュ」を使うように変更する
目的:
プライバシー保護: 誰が誰にお金を払っているのか、簡単に見られないようにする
管理の効率化: 名前と公開鍵の対応表が不要になる
送金依頼時に送金先を指定するのにも公開鍵ハッシュを使う
入力ミスのリスクが高まる
送金先を間違えたCTは誰も使えない。燃やしたに等しい
入力ミスのリスクを抑えるために、公開鍵ハッシュを変換した「クッキートークンアドレス」を使う(クッキートークンアドレス = ビットコインアドレス)
3.1 クッキーの習慣
原著での節タイトルは "Cookie-eating habits disclosed" (「クッキーを食べる習慣の暴露」)
2章終了時点でのCTシステムの問題点のまとめ。
プライバシー
CTの取引レコードには「XからYに、いくら支払ったか」(X, Yは個人名)という情報が記されている。CTの取引履歴からは個々人の支払い傾向が丸見えになので、その流出はプライバシーの侵害につながる。
公開鍵管理の煩雑さ
送金依頼の署名検証時、管理者はいちいち送金者の名前からその人の公開鍵を探す作業を行う必要がある。また、新規ユーザが増えるたびに名前と公開鍵の対応表を更新する必要がある。
やたら「アクメ保険」が気になったが、「コーポレートファイナンスの原理」という本でも登場するらしい。erechorse.icon 3.2 名前から公開鍵へ
取引レコードに送金者・受領者の名前を記す代わりに、二者の公開鍵をそのまま記録すれば、これらの問題を解決できる
プライバシー: 名前と公開鍵の対応関係を知らない限り、直接的に個々人の支払い傾向を知ることはできない
支払額や支払い頻度といったデータから、公開鍵が誰のものかを推測することまでは防げないが…
管理の煩雑さ: 名前と公開鍵の対応表が不要になる
送金依頼時にも送金者・受領者の名前の代わりに公開鍵を記載する必要がある。
送金依頼に含まれる構成要素:
以下を含むメッセージ
金額
送金者の公開鍵
受領者の公開鍵
送金者の秘密鍵によるメッセージにへのデジタル署名
新規ユーザが管理者に自分の公開鍵を伝えて対応表に追加してもらう、という段取りも不要になり、単に自分に送金したいと思っている人に自分の公開鍵を伝えるだけでよくなった。
注意: CTの管理者は、送金依頼メールの差出人と(そのメールに書かれている)送金者の公開鍵を紐付けることができる
公開鍵暗号方式を使うのは、匿名性を維持するため。インターネットにおける同一性を証明する方法が公開鍵erechorse.icon
3.3 公開鍵の短縮
名前に比べて公開鍵のデータサイズは大きい(圧縮形式でも33byte)。セキュリティを維持しつつもっと短いデータに置き換えられないか?
→ 公開鍵を、より出力サイズが小さい暗号学的ハッシュ関数に通す
3.3.1 公開鍵をハッシングして20バイトに
公開鍵をSHA-256でハッシュしたあと、RIPEMD-160という別のハッシュ関数に通して、160bit(20byte)の[* 公開鍵ハッシュ(Public Key Hash, PKH) を生成する。
公開鍵の代わりにPKHを取引レコードに記録するように変更する。また、送金の宛先(受領者)の指定にもPKHを使うようにする。
送金者の公開鍵はPKHにしない(送金者によるデジタル署名の検証に公開鍵そのものが必要なので)。送金者の残高確認と取引レコードの作成にあたり、管理者は送金者の公開鍵から改めてPKHを計算することになる
(公開鍵そのものではなく)PKHで受領者を指定するタイプの支払いのことをpay-to-public-key-hash、略してP2PKHと呼ぶ。
注意:
公開鍵をPKHに置き換えてもプライバシーは向上しない。
公開鍵とPKHは1:1対応なので
3.3.2 なぜSHA-256とRIPEMD-160の併用なのか
どうしてわざわざ2種類のハッシュ関数を併用するのか?
2つめの暗号学的ハッシュ関数にRIPEMD-160を用いるのは、PKHをもとの公開鍵より短くするため。
公開鍵を直接RIPEMD-160に入力するのではなく、わざわざSHA-256を組み合わせる理由について、設計者のサトシ・ナカモトの意図はよくわかっていない
複数のハッシュ関数を合成した関数の性質: もとのハッシュ関数すべての原像計算困難性が破られない限り、それらを合成した関数の原像計算困難性も破れない
与えられたPKHからRIPEMD-160に対する入力が計算できても、SHA-256が原像計算困難である限りは公開鍵を復元できない
任意のSHA-256のハッシュ値から入力を復元できたとしても、RIPEMD-160が原像計算困難である限りはもとの公開鍵を復元できない(与えられたPKHに対応する入力がわからないので、結局総当りするしかない)
衝突耐性に関しては、SHA-256の衝突耐性が破られた時点でSHA-256とRIPEMD-160の合成関数の衝突耐性も自動的に破られたことになる。
RIPRMD-160の衝突耐性のみが破られた場合は問題なし
監訳者の説は、PKHのセキュリティ(=アドレスのセキュリティ)をSHA-256の強度で守るために、SHA-256を組み合わせたのではないかというもの
なお、SHA-256の開発元はNSAである一方、RIPEMD-160の開発元はオープンな暗号学者コミュニティである。
ただし、他の部分はダブルSHA-256を使っているため、NSAの技術への依存を避ける目的があったとは考えづらい
今やサトシの意図を推測するしかないという状況が少し興味深い。この会話がどこでやり取りされたのかちょっと見たい。erechorse.icon
3.4 高くつく入力ミスを避ける方法
管理者は、送金の受領者(欄に記載されたPKH)が有効かどうか検証しない。
送金時に宛先のPKHを間違えれば、そのお金は誰にも使えないものとなり、消滅したのと同然となる。
→ 入力ミスを未然に防ぐための仕組みが必要
PKHの代わりに、それに変換を加えたクッキートークンアドレス(=ビットコインアドレス)を使うことで入力ミスの問題を防止する。具体的には、PKHをbase58checkでエンコードしたものをクッキートークンアドレスとする。
クッキートークンアドレスは、エンドユーザがPKHを取り扱う場面(例: 自分に送金したい人に対して自分の送金先を示すとき)に限って用いられる。
取引レコードにはアドレスではなくあくまで元のPKHを記録する
base58check符号化
ポイント:
チェックサムにより入力ミスを高確率で検出可能
100%ではない
形が似ている文字や記号を排除することで、入力ミス耐性や利便性を向上
符号化(エンコード)のステップ:
1. PKHの先頭にバージョン番号(1バイト、現在のバージョンは0)を追加
2. 1.の結果にダブルSHA-256を適用した結果の先頭4バイトをチェックサムとする。このチェックサムを末尾に追加
この時点でデータ長は20+1+4=25バイト
3. 2.の結果をbase58で符号化
base58: base64で使う文字からl, I, 0, Oの4文字と記号2文字を除いた58文字によって、データを58進数として表現するエンコーディング
さらに、元データにおける先頭の「00」バイトの数だけ先頭に「1」を追加する
形の似ている文字を除くことで、入力ミスのリスクを最小限に抑える
記号を除くことで、
変な位置で改行されないように
常にダブルクリックで全体を選択できるように
要は58進数変換(淀川)
最終的なビットコインアドレスの長さは最大34文字で、先頭の文字が必ず1になる
復号時には、base58復号後にチェックサムの検証(末尾4バイトを除いてダブルSHA-256をとり、末尾4バイトと等しいかチェック)を行う。この検証で入力ミスを検出できない確率は1/2^32(約1/43億)。さらに先頭のバージョン番号を取り除いたのが元のPKH。
脱線: 別形式のアドレス
ここで取り上げられているビットコインアドレスの形式は現在では「レガシーアドレス」と呼ばれるもので、現在はbc1から始まるアドレスも用いられている
bc1から始まるアドレスへの支払いは、セグウィット(SegWit、詳細は10章)という新しい仕組みで処理される
よって、bc1から始まるアドレスを「(ネイティブ)セグウィットアドレス」と呼ぶ
中身はレガシーと同じくPKHだが、符号化方式は(Nostrプロトコルではおなじみ)bech32に変わっている
アドレスの形式は、受領者が受付可能な支払い形式を反映している。
送金者(のウォレット)は、送金先アドレスに基づき適切な支払い形式を選択する。
例えばあとで出てくるP2SHという形式の支払いの場合、アドレスの先頭が1ではなく3になる
base58(読みやすく、)check(入力ミスを防ぐ) erechorse.icon
ダブルSHA-256はなんのため?erechorse.icon
2回かけているのは安全性の確保?
色んな所で使われているのは、複数のアルゴリズムを使いすぎるとややこしいから?
3.5 再びプライバシーについて
取引レコードに名前の代わりにPKHを記録するようにすることで、プライバシーの問題は改善されるが、完璧ではない
例: 大量の10CT(1枚のクッキーを買うのに必要な金額)を受け取っているPKHは、おそらくカフェのもの
支払いごとにアドレスを変更すれば、取引履歴から意味のある情報を抜き出しづらくなる
支払いごとに新しいアドレス(元をたどれば秘密鍵)を生成する世界観で、すべてのアドレス(=秘密鍵)をいかに管理するのか?