ビットコイナーはシードフレーズの生成からこだわる。そういうキャッチコピーがあるわけではないですが、昔から「ガチ勢」はウォレットのシード生成にかなり気を配っているのも事実です。なぜなら、ランダム性の低いシードを生成してしまうと資金を盗まれてしまう可能性があるためです。

実際、最近でもMilk Sad脆弱性を本稿で取り上げていますが、ソフトウェアウォレットが疑似乱数から生成するシードに脆弱性があったという事件は定期的に起こっています。起こった頃には手遅れな可能性のある重大なリスクなので、電子機器やソフトウェアに頼らない、確実なランダム性を求めたいところです。

Libbitcoin Explorer (bx)に深刻な脆弱性。Milk Sad脆弱性とは
今週、ビットコイン関連の技術者にとって衝撃的なニュースが発表されました。Libbitcoin Explorer (bx)というツールにシード生成の脆弱性があり、このツールを利用して生成されたウォレットから資金が盗難されているというのです。 Trust Walletなども最近シードの生成に関する脆弱性で大きな流出を起こしている中、ノンカストディアルウォレットで同じような問題が相次いでいることになります。せめてもの救いは人気のウォレットであるTrust Walletと比較してLibbitcoinは老舗ながら近年ほとんど使われていないことでしょう。 Milk Sad脆弱性について解説していきます。 ・Libbitcoinはビットコイン関連のウォレットやアプリケーションの作成に使える老舗C++ライブラリ ・エントロピー不足とMilk Sad…で始まるシードフレーズ ・意図的に仕込まれていた?という疑惑について milksad.info

そこで今日は一般的なサイコロによる乱数生成を取り上げます。直近だとTokyo Bitcoin Baseで開催された反省会万博においてサイコロでシードフレーズを生成するワークショップなどありましたが、よく聞かれた声として「本当にこれで安全な乱数が生成できているか自信がない」というものがありました。今日はこの疑問に答えるとともに、本当にサイコロを使った乱数生成にこだわるべきかを含めて考えていきましょう。

・シードフレーズの元となる「エントロピー」とは

・サイコロでのシード生成手順はかなりシンプル

・どれくらい偏ったサイコロだと脆弱なシードになってしまう?

・ハードウェアウォレットによる生成と比較して積極的に選ぶべき選択肢なのか?

💡
この記事内の計算がもし間違っていたらご指摘ください。結論から言えば、心配なら24単語のシードフレーズを生成すれば基本的に大丈夫です。

シードフレーズの元となる「エントロピー」とは

ビットコインウォレットを扱ったことのある人は、避けて通れない「シードフレーズ」に一度は直面したことがあるでしょう。一般的に12単語または24単語からなるシードフレーズは、それぞれの単語が2048個のリストからランダムに選ばれたもので、それぞれが固有の11ビットの情報に対応しています。

こんな風に、各単語が2進数11桁に対応しています

そしてこの単語をつなぎ合わせることで、「シード」というウォレットの大元となる乱数が復元できます。すなわち、12単語のシードフレーズは128ビットのシード、24単語は256ビットのシードを表します。

💡
12×11 = 132 > 128, 24×11 = 264 > 256と厳密に計算が合わないのは、最後の単語が誤り検出用のビット列(チェックサム)になっているためです。もし途中の単語を誤って入力すると、最後までシードフレーズを入力したときに「誤りがある」と高確率で検知できます。

シードが流出したり推測されるとそのウォレットは他人に使われてしまうので、シードを生成するときに十分なランダム性のある情報源を使う必要があります。このランダム性、そして特に鍵生成においてはそこから得られる情報(ランダムなビット列)のことをエントロピーと呼びます。

例えば理想的なコインは1回投げたら「表」「裏」のどちらかの値を等しい確率でとるので、コイントスには1ビットのエントロピーがあるといいます。連続で試行しても、それぞれの試行が独立している(互いに影響しない)限り10回試行すると10ビットのエントロピーが得られます。

ただし、そのためには条件がランダムなコイントスでなければなりません。手やコインの位置、力、気温などが全く同じだとそれぞれの試行の独立性が失われます。「狙って表を出す」ような投げ方を考えるとわかりやすいです。

PCやスマホに搭載されている擬似乱数生成器は、その小ささからくる物理的制約や電気で動く特性によって得られるエントロピーが偏りやすいので、様々な工夫でランダム性を高める必要があります。一方で人間はコイントスやサイコロという手軽で質のいいエントロピーを得られるので利用しよう、というのがビットコインのシード生成にサイコロを使う理由です。

サイコロでのシード生成手順はかなりシンプル

サイコロでシードを生成する手順は何種類かありますが、シンプルなものを紹介します。

サイコロを5つとコインを1枚用意して、サイコロを十分にランダムに振ります。(手の中でいろんな時間降ったり、筒を用意して筒の中でしっかり振るなどします。基本的には毎回同じ振り方してるな~とか毎回同じ出目でスタートしてるな~とならなければいいです)

サイコロの出目をシードフレーズの単語に変換する表がいくつかあるので、出目をサイコロの位置によって左から右、上から下へと読んで、当てはめます。サイコロ5つの場合は最後にコイントスを1回する必要があるので、コイントスします。このときもできるだけランダムを心がけましょう。(毎回表からスタートするみたいな調整をせず、トスするときの力や高さも一律にしないようにしましょう)

Roll your own Bitcoin seed
Learn how to create your own random Bitcoin hardware wallet seed with these easy step-by-step instructions.

ハードウェアウォレットメーカーのBitBoxが紹介している手順の例です

こうしていくと単語が11個、あるいは23個生成できます。最後の1単語だけはチェックサムを兼ねているので手動では難しいので、ハードウェアウォレットなどでシードフレーズから復元することになります。(最後の1単語の選択肢もいくつかあるので、これも好きな方法でランダムに決めましょう。好きな単語ではなく、あくまでランダムに選ぶことが重要です)

シンプルな方法はこれだけです。あまり時間もかかりませんし、思ったより簡単だったという方も多く、逆に不安に思ってしまう気持ちもわかります。

どれくらい偏ったサイコロだと脆弱なシードになってしまう?

一番の心配はランダム性が不足していないかでしょう。そこで、仮に偏ったサイコロをシード生成に使ってしまったとき、どれくらいからセキュリティに有意な悪影響を及ぼしてしまうのか考えてみます。

極端な例として、1,2,5,6の面しか出ないダイスを考えてみましょう。

上で紹介したアルゴリズムだとサイコロの出目は1~4しか使わないので、ダイス5個だと各単語についてわずか2048/32=64単語のプールから選ぶことになります。言い換えると、1単語あたり11ビットのエントロピー(1/2048)のはずが、実際には6ビットのエントロピー(1/64)しか得られていないわけです。

単語数 本来のエントロピー このケースのエントロピー
12 128 73
24 256 141

12単語のシードフレーズの場合、最後の単語をランダムに選べていたとしても(7ビット)、66+7=73ビットのエントロピーにしかなりません。厳密には違いますが、12単語中5単語以上バレているようなランダム性なので、さすがに好ましくないです。

でも、24単語のシードフレーズだったらこれでも138+3=141ビットのエントロピーがあります。完全にランダムな12単語のシードフレーズより多いですね。そして実際にはここまで偏ったサイコロを使うことはないでしょう。なので、不安なら24単語分のシードを生成するのがまずは正解です。そもそも多少の製造誤差があっても普通のサイコロを使っていれば基本的に脆弱なシードにはなりません。

サイコロの調達で対策するのはコスパが微妙

ほぼ偏っていないサイコロを買うこともできます。カジノダイスといい、中に気泡やオモリが仕込まれていないか確認できるように透明で、ほぼ完璧な立方体で、出目も凹んだり出っ張ったりせず、本体と同じ比重の色だけが異なるプラスチックでできています。もちろん、原子レベルで完璧なわけではありませんが、これを買ってシードを生成するビットコイナーも多いです。

ただ、256ビットのシードを生成するならここまでする必要はないと思います。

ちゃんとしたカジノダイスは5000円前後する

偏ったサイコロを補正するアルゴリズムも存在

他にも、偏ったサイコロやコインの影響を補正するアルゴリズムも存在します。数学者フォン・ノイマンが発明したアルゴリズムで、過去の記事で紹介しているので興味がある方はそちらもご覧ください。

紙とペンでシャミアの秘密分散法を使いシードフレーズを分割する:Codex32
コアなビットコイナーは秘密鍵の管理にうるさかったり、一家言ある人が多いというイメージはありませんか?少なくとも自分の印象ではWeb3系の人たちよりよほど秘密鍵の生成や管理に関心がある気がします。 ビットコイナーの一部の間ではマルチシグによって自身のコールドストレージのセキュリティを強化する人も見られるようになりました。しかし通常のシードフレーズとは異なり、複数のシードフレーズとスクリプト文のデータなどを用意し別々の場所で安全に保管するのが煩雑なのも間違いありません。 他にはシャミアの秘密分散法という知名度の高い手法を使って1つのシードフレーズを複数の「シェア」に分割し、それらのシェアを使ってn-of-mのマルチシグを擬似的に再現することも考えられます。実際には1つのシードフレーズを復元するので狭義のマルチシグトランザクションにはなりませんが、比較的シンプルな手法で(ビットコイン以外のブロックチェーン系のウォレットで)人気があります。 例えば友人や親戚にシェアを1つ預けてソーシャルリカバリーできるようなウォレットの多くはこのスキームになっています。数人に結託して裏切られないように注

異なるエントロピー源を組み合わせる対策も考えられる

先程軽く振れましたが、電子機器の擬似乱数生成器は複数の(できる限り相関しない)乱数源を組み合わせることでランダム性を強化しています。人間も同じアプローチを取ることができるので、例えばさっきの手順と同時にコイントスをして、表ならそのまま、裏なら全ビットを反転(0→1、1→0)させれば単純にエントロピーが2倍になります。

Coldcardなどダイスやコイントスによるシード生成をサポートしてくれる機能があるハードウェアウォレットにも、ダイス単体ではなく他のエントロピー源も組み合わせる設定が入っていたりします。

COLDCARD - The Most Trusted and Secure Signing Device (a.k.a. Hardware Wallet)
COLDCARD Is The Most Trusted and Secure Bitcoin Signing Device (aka. Bitcoin Hardware Wallet)

ハードウェアウォレットによる生成と比較して積極的に選ぶべき選択肢なのか?

ハードウェアウォレットのシード生成が脆弱だった事例は(私の知るところ)ないですし、製造元に悪意がなければ24単語の生成であればそうそう起こり得ない話だと思います。なので、ハードウェアウォレットが生成するシードを信頼するのも理解はできます。

しかし、仮に悪意があって脆弱性が仕込まれていたことが発覚したらその時点で手遅れな可能性があります。脆弱なシードはその後もずっと脆弱です。その対策として、自身でシード生成するのも大いにアリなんじゃないでしょうか。

💡
いずれの場合も、生成したシードから導かれるウォレットが別々のメーカーのハードウェアウォレットで本当に同じものなのか検証することも(=ハードウェアウォレット自体が信頼できるかも)、大きな金額の保管になってくると大事なことだと思います。

まとめ

・サイコロでシードを生成する場合、24単語のシードフレーズを生成する手順を踏めば完璧なダイスや完璧な振り方でなくとも基本的には安全である(できる限りランダムを目指すことはもちろん大切)

・サイコロの出目に加えて、ハードウェアウォレット側でエントロピーを追加してくれる機能があるものもある

・ハードウェアウォレット単体に依存するより少し手間はかかるが、安全性は高いので、特に金額が大きい場合は自身でのシード生成をぜひおすすめしたい