ビットコインで使われるアドレスの話

初めまして、コインチェックで暗号資産の入出金周りを担当しております、やなぎーです。記事を書くのは、仕事でもプライベートでも、最近は殆どないのですが、なんだか、技術ブログを書くようにと、お達しがあったので、今回は利用者に最も馴染みが深いであろうアドレスについての話をしたいと思います。アドレスの話に入る前に、まずは、公開鍵暗号の概要から、話を始めます。あと、最近、誤入金が増えていますので、暗号資産の入金の際はアドレスとタグの確認をお願い致します。

公開鍵暗号 (Public-key cryptography) によるプライバシー

公開鍵暗号が発明されるまで、暗号文は、中間者による秘密鍵の傍受というリスクにさらされていました。暗号化と復号の両方で、同じ鍵を用いるからです。ある鍵を使って暗号文を作成し、それを送信するまでは安全ですが、暗号文の受信者は、復号の為に、その鍵も何らかの方法で共有してもらう必要がありました。これでは、インターネットの時代に、暗号文を電子メールで送信した後に、鍵を封筒に入れて書留で渡す必要があります。そして、この鍵の受け渡しには、傍受のリスクが伴います。これを鍵配送問題といいます。

第二次世界大戦中に、解読不可能と言われていたエニグマでさえ、通信兵の捕虜を捕まえて、鍵を盗めば終わりです。そのため、定期的に鍵を入れ替えるという大変な作業が行われていました。安全に、受信者の全員に、そして定期的に、鍵を配送しなければならなかったのです。(エニグマの解読の原因は、設計書が漏れるというオープン・デザインの認識の欠如、ポーランドのボンブの発明、それを引き継いだイギリスの粘り強い努力によります)

公開鍵暗号の画期的なところは、暗号化と復号で、同じ鍵を利用する必要がないということです。暗号文の受信者は、先に錠(公開鍵)を送信者に渡し、送信者は、その錠でロックをかけて暗号文を受信者に渡します。受信者は、自分だけが持っている鍵(秘密鍵)を使って、ロックを開放すれば良いのです。ここで、鍵の配送は発生しません。配送されるのは錠であって、これは傍受されても問題ありません。これを公開鍵暗号といいます。このアイディア自体は、1960 年代からあって、数学的に実現する方法(RSA)が発見されたのが、1973 年のことでした。

インターネット上のプライバシーは、この公開鍵暗号の発明によって、支えられています。ネットで何を買っても、中間者に知られることはありません。ありがたい話ですね、我が家では直ぐ箱を開けられてしまいます。給与明細を渡す時には茶封筒に入れるように、募金をする時には実名を伏せるように、プライバシーとは、社会的公正な理由によって、当然の権利として認められるべきものです。 (人の郵送物を勝手に開けないでください)

ビットコインの支払いも、完全なプライバシーを持っています。だからといって、違法なものを買ってはいけません。ビットコインにおける取引は、完全な透明性も兼ね備えており、その取引は確実に追跡可能です。これは覚えておいてください。また、暗号資産の中には、匿名性を兼ね備えたものもあるのですが、悪い物事に暗号資産を利用することは、暗号資産の悪用であり、開発者の意思にも反しており、当然、これは認められるものではありません。

公開鍵を共有するためのアドレス形式 Base58Check

【3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd】bitcoin.org

暗号資産におけるアドレスというのは、端的に言えば、公開鍵のことです。自分の公開鍵を送金者に公開しておいて、送金者が支払いを行いたい時に、その錠を使ってロックをかけることで、送金を行います。つまり、送金者が相手のお財布にお金を入れて錠を閉めるのです。その錠を開けられる鍵を持っているのは受信者だけです。このロックの解除は署名と言う仕組みで実現されています。

この公開鍵は数学的には非常に長いバイナリのビット列です。このビット列は、傍受されても問題ありませんが、共有するには細心の注意が必要です。前提として、ネットというのは不安定 (我が家のネットはよく切れます) なので、長いビット列を 1 bit の狂いもなしに、完璧に受け渡せることは保証されません。アナログに紙に書いて渡しても同じことです。情報の理論において、一般に、コミニュケーションには、必ず、このような雑音が含まれます。また、人間であれば、打ち間違いも発生することでしょう。誤って秘密鍵のない公開鍵で資産をロックしてしまったら、これを取り出すことは誰にもできなくなります。

Base58Check は、公開鍵を取り扱いの簡単な文字列として表現するための仕様です。見慣れたアルファベットを使って、尚且つ、O(オー)と0(ゼロ)などのミスリードする文字は除外して、表現されます。ニンテンドー Switch のギフトコードもそうですね。また、打ち間違いや伝送エラーを検知するために、末尾にチェックサムも付与されます。このように表現された公開鍵をアドレスと呼んでいます。

public_key を公開鍵として、アドレスは、以下の式で導出されます:

payload = RMD160(SHA256(public_key))
data = version + payload
address = Base58(data + Checksum(data))

Checksum(m) := SHA256(SHA256(m))

ここで使われている Base58 はバイナリを、アルファベットで表現する仕様です。アドレスは、チャットやメールに簡単に貼り付けられるように、バイナリではなく、アルファベットで表現されていると都合が良いですよね。電子メールは元々テキストを送信するために発明されたので、画像などのバイナリデータを渡したい時は Base64 が使われています。Base58 は、この Base64 の文字セットから、ミスリードの可能性のあるアルファベットを除外しています。

そして、アドレスの末尾にはチェックサムが付与されていて、これを確認すれば、打ち間違いや、コピペによる先頭文字や末尾文字の漏れや、伝送エラーによる一部の文字の改変も、事前にガードすることができます。

ミステリアスな Double Hash の真相

ビットコインで使われているハッシュ関数は謎が多いです。Base58Check のチェックサムでは、二重ハッシュが用いられています。m をメッセージとして、SHA256(SHA256(m)) という式で表されます。これは ビットコインのコード上の色々なところで、用いられているハッシュ関数です。一般に、ハッシュを二重で利用することは、セキュリティ的に推奨されません。m が十分なエントロピーを持っていたとしても、一つ目のハッシュで、情報量が少なくなってしまうので、二つ目のハッシュの出力の衝突確率が上がります。暗号学的ダイジェスト関数の要は、衝突確率が低いことです。

medium.com

ダブル・ハッシュの謎に関して、こちらの記事に考察が書かれていますので、読んでみると面白いと思います。しかし、究極のところ、サトシ・ナカモトが何を考えて、これを採用したのか、今となっては、真相は「藪の中」です。

因みに、芥川龍之介の「藪の中」は、7人の証人の内の複数人が嘘をついているので、論理学的に真犯人が見つけられないという、ビザンチン将軍問題を描いた作品です。不特定多数の人間が参加する分散型のシステムにおいて、本当にガバナンスを成立させることができるのかというのは、長らく理論上の話であって、現実の世界で可動できたシステムは存在しませんでした。ビットコインは PoW (Proof-of-Work) という手法を用いることで、参加者が真実を語ることを保証しています。

エラーの検知率が上がった Bech32 (BIP-173)

【tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7】BIP-173

公開鍵暗号の公開鍵を元に宛先を表現する Base58Check という賢い仕様は、Ripple (但し、アルファベット・テーブルが異なる) など、後発の暗号資産にも受け継がれています。しかし、弱点も存在します:

  • 大文字・小文字が混在しているので、QR コードで表現した時に、サイズが大きくなってしまう
  • チェックサムが、単なるハッシュ関数なので、チェックはできるが、検知の精度に対して数学的な保証がない

Segwit (Segregated witness) で導入された新アドレスは Bech32 形式で表現されています。これは以下の点で、改善が行われています:

  • 小文字オンリーなので、QR コードが小さくなる
  • チェックサムに BCH符号を用いているので、エラー検知の精度に関して、数学的な保証がある

あと、アドレスの先頭に HRP (Human-Readable-Part) という部分が導入され、ここにエンコードなしにアルファベットを追加できるようになりました。ビットコインでは、この部分にアドレス・バージョンを示すアルファベットが付与されているので、チェーンの違いが、アドレスを見ただけで分かるようになりました。ビットコインの仕様は他の通貨に受け継がれるので、この識別ができることは、ありがたいことです。

因みに、HRP のセパレーターとして 1 が採用されていて、これはマウスでダブル・クリックして単語を選択した際に、切れないようにする配慮によるものです。記号だと切れてしまいますよね。

Bech32 の脆弱性に対応した Bech32m (BIP-350)

【tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c】BIP-350

Bech32 にはローンチ後に脆弱性が発見されました。チェックサムの計算式に問題があり、特定のパターンで q という文字をいくらでも挿入可能です。これでは打ち間違いをガードするチェックサムとしては問題です:

ii2134hk2xmat79tqp
ii2134hk2xmat79tqqp
ii2134hk2xmat79tqqqp
ii2134hk2xmat79tqqqqp

(https://github.com/sipa/bech32/issues/51 より引用)

Base58Check のチェックサムの設計に課題があり、それを改善した Bech32 のチェックサムの設計に脆弱性が発見されるのは、セキュアなソフトウェアの設計を行うということの難しさを物語っています。

Bech32m ではチェックサムの計算式を修正しています。このアドレス形式は、今後の新アドレスのために策定され、Taproot ソフト・フォークに盛り込まれており、将来的に普及していくと思われます。

エンジニアを募集しています

以上で、アドレスの話はおしまいです。もし、この記事を読んで、暗号資産の技術に興味を持っていただけたら、幸いです。

コインチェックでは優秀なエンジニアを通年募集しています。

https://corporate.coincheck.com/recruit/jobsearch/engineeringcorporate.coincheck.com