Coldcardの事件をきっかけに、ハードウェアウォレット(HWW)に備えられた乱数生成器に頼らず、自分で乱数を作ってシードフレーズを作ることへの関心が広がっています。自分で作った乱数であれば、Coldcardの事件のような乱数生成器のバグや障害による影響を受けませんので信頼する対象をひとつ減らすことができます。

Coldcardの乱数脆弱性事件についてキャッチアップしたい方は以下の記事をご覧ください。

【重要】COLDCARDユーザーの方へ|シード生成に脆弱性の影響範囲と移行の判断基準
2021年3月配信のCOLDCARDファームウェア4.0.x以降、シード生成が脆弱な乱数経路を通っていたことが判明しました。2026年8月時点で現行機種を含む広範囲が対象です。該当条件の確認方法と、慌てずに移行を進めるための手順をまとめました。

自分で乱数を作る方法は様々なものがあります。サイコロやトランプで作る方法、マウスカーソルの動き、画像データなど様々です。現在はサイコロが王道のシードフレーズ生成方法であり、実践的な方法について知りたい方は以下の記事もご参照ください。

セルフカストディは最初が肝心|サイコロ・トランプで安全なシードフレーズを生成する実践ガイド
Coldcardの乱数生成における脆弱性を受けて関心が集まっている、サイコロやトランプによるBIP39シードフレーズの生成について、その安全性の根拠となる数学とともに、実際の生成手順を紹介します。その上で、機械に生成させたエントロピーと比較したトレードオフについても解説します。

王道のサイコロの出目(以下、サイコロ乱数)を元にしたシードフレーズ生成について一点大きなデメリットがあります。それは、サイコロ乱数をハッシュ関数(SHA256)に入れてシードフレーズを作るため、実際に自分のサイコロ乱数が使われているのかを事後的に検証できない点にあります。

悪意や欠陥のあるHWWであれば、サイコロの出目をSHA256に通した結果を使用せず、別の脆弱な乱数生成器の結果を使用している可能性も0ではありません。

本稿では、最も王道とされるサイコロ乱数を元に生成したシードフレーズが、本当にサイコロ乱数を元にしているかをクロスチェックする方法についてSeedSignerを用いて解説します。具体的には、同じサイコロ乱数を用いて「SeedSignerでのシードフレーズ」と「Webアプリでのシードフレーズ」が一致すれば、本当にサイコロ乱数が使用されたということを確認できます

ぜひ動画でも検証をおこなっていますので、参考にしていただければと思います。

💡
Coldcardでのサイコロ乱数を用いたシードフレーズでも同様に検証可能です。ビットコイン研究所のYouTube動画を参照ください(「ダブルチェック」と「クロスチェック」を同義で使っていますが、言葉としては「クロスチェック」の方が正しそうです)

サイコロ乱数のクロスチェックの意義とは

※今すぐ実演したい方は「SeedSignerを用いたクロスチェックの実践」まで読み飛ばしてください

実際にサイコロ乱数のクロスチェックをする前に、そもそもクロスチェックの意義について解説します。

以下の図は、24単語のシードフレーズができるまでの仕組みとなります。

24単語シードフレーズ生成の全体の流れ

左から流れに沿って解説します。

  1. サイコロ乱数:サイコロを99回以上回して出目を入力(99回で256bit相当のエントロピー)
  2. Hash SHA256(Text):サイコロ乱数を文字列としてSHA256関数に入れます
  3. 256bit(2進数 256桁):2のSHA256出力値は256bitです
  4. Hash SHA256(bin or hex):3の256bitをbin(2進数)かhex(16進数)としてSHA256関数に入れます
  5. (256+頭8)bit(2進数 264桁):3の256bitに、4の冒頭8bitを結合し、264bitを作ります
  6. シードフレーズ(24単語):264(bit)÷24(単語)=11(bit)となり、11bitで1単語が表現されます

コンピュータしかできない関数的な処理は、ビットコインのマイニングなど様々な場面で使用されるハッシュ関数の「SHA256」のみとなっています。

SeedSignerとColdcardではたまたま同様の方法でサイコロ乱数から「3. 256bit(2進数 256桁)」を生成しますが、コイントス(0,1)を256回実施すれば直接「256bit(2進数 256桁)」を作ることも可能です。「3. 256bit(2進数 256桁)」を用意する方法は各ウォレットによって異なります。

実際にSeedSignerやColdcardにてサイコロ乱数を元にシードフレーズを作る際、サイコロの出目を入力(一番左の「サイコロ乱数」)すると、内部処理がなされ、いきなり右側の「シードフレーズ」が画面に表示されます。しかしながら、表示されたシードフレーズが本当にサイコロ乱数を元に生成されたかの検証は事後的には困難です。

具体的には、以下のようなリスクがあります。

悪意のあるシードフレーズ生成例

サイコロ乱数を使ったSHA256の出力値は不可逆であり、さらにランダムな数字列であるため、緑色の弱い256bitに置き換わっていたとしても気付くことができません。

これまで「サイコロ乱数が結局使われなかった」という上図のような事件は確認できていませんが、クロスチェック後のウォレットで作ったシードフレーズであれば、今後起き得る乱数脆弱性の問題から切り離すことが可能となります。

また、クロスチェックによりシードフレーズ生成においてバックドアが仕掛けられた偽ファームウェア、またはアップデートのバグにも事前に気付くことができます。

Coldcardの乱数脆弱性事件はどこに問題があったか

Coldcardのシードフレーズ生成方法

Coldcardでは以下のようなシードフレーズ生成方法がありました。

  • 12単語
    • 12 Words
    • 12 Word Dice Roll
  • 24単語
    • 24 Words
    • 24 Word Dice Roll

単語数をXとすると「X Words」と「X Word Dice Roll」という2種類です。後者の「X Word Dice Roll」はサイコロを振る手間があり上級者向けとされていたので、前者の「X Words」を使っていた方の割合が多いのではないかと考えられます。

「X Words」ではハードウェア内蔵の真性乱数生成器(TRNG)がランダムな乱数を作り、任意でサイコロ乱数を加えられるというものでした。しかしながら、コードの条件分岐によりTRNGが使われず、擬似乱数生成器(PRNG)というある程度探索範囲が絞られる方が使用されていました。

結果として、mk3では約40bit、mk4以降では約72bitのランダム性(エントロピー)となってしまいました。128bitあれば十分なシードフレーズ生成において、40bitはかなり小さい水準となります。

一方で「X Word Dice Roll」でシードフレーズを生成した場合は、ハードウェア内蔵の乱数が一切使用されず、サイコロ乱数の最低入力数の基準も設けられていたため問題ありませんでした。

韓国ではサイコロ乱数でのシードフレーズ生成が推奨されていた経緯もあり、Coldcard事件の被害者は少なかったと言われています。

韓国のビットコインユーザーはコールドカードの危機をどう乗り切ったのか、そしてそれが私たちに明らかにした問題点とは?(Koji Higashiさん)

SeedSignerを用いたクロスチェックの実践

サイコロ乱数のクロスチェックの意義について解説しました。

次はSeedSignerを用いて実際にクロスチェックを行います。クロスチェックというのは、サイコロ乱数を元にSeedSignerでシードフレーズを作り、同じサイコロ乱数を用いてWeb等でサードパーティアプリを使用して同じシードフレーズが出力されるかを確認します。

同じシードフレーズが確認できれば、使用したSeedSignerのシードフレーズ生成部分は正常に機能していることが確認できます。

ちなみに、Coldcardも同様の仕組みであるため同様にクロスチェックが可能です。お手持ちのHWWがあればお試しください。

💡
注意点:クロスチェックで使用したサイコロ乱数・シードフレーズについてはデジタル上に情報が残る可能性があるため、絶対に実利用しないでください。

クロスチェックによってHWWのサイコロ乱数による生成部分が確認でき、同じ挙動であればクロスチェック後に作ったシードフレーズも同様に安全であると捉えることができます。

①サイコロ乱数を作る

サイコロ乱数を作ります

まずはサイコロ99回分を紙やPCなどに記録していきます。サイコロは6面サイコロを使用します。(24単語のため99回分を記録します)

自分の方で作成した99回分のサイコロ乱数はこちらです。

346314616632343521235326436331312443521254515431641554542166543251122545154245653432165642544226231

②SeedSignerでシードフレーズを生成

SeedSignerがシードフレーズまで導きます

次にSeedSignerでシードフレーズを生成します。

SeedSignerの操作

上図のように操作し、先ほど記録したサイコロ乱数を打ち込みます。

SeedSignerでは入力を戻すこともできますので、間違いがないか確認しながら進めましょう。

自分の手元で出力されたシードフレーズは以下のようになります。

cable exclude they twice sugar delay exist female improve beauty bring betray awful vivid beyond cool rib napkin melody traffic taxi glue market tiny

③Webアプリでシードフレーズが一致するかクロスチェック

クロスチェックとして、Web上のサードパーティアプリを用いて同様のシードフレーズが出力されるかを確認します。

サイコロ乱数を256bitにします

サイコロ乱数はすでに存在するので、SHA256(Text)の処理までを進めます。SHA256の出力はどのサイトでも、Terminalでも問題ありません。本稿では以下のサイトを利用します。

Sha256 Algorithm Explained
Sha256 algorithm explained online step by step visually

他のSHA256でも問題ありません

TextとしてSHA256を通します

SHA256の処理する文字の種類によって結果が変わるので「Text」であることはご確認ください。出力値の16進数(2進数にすると256桁)をメモします。

1fe9df8275ad8c73d3f2a7720274708ab10bea45717eb8f25e2a736de6c7e20f
256bitのエントロピーからシードフレーズを作ります

最後に「Mnemonic Code Converter」というサイトに入力して、シードフレーズを出力します。

https://iancoleman.io/bip39/

💡
Ian Colemanは、BIP39ニーモニックコード変換ツールの開発者です。ソフトウェア開発者であり、セキュリティ分野にも詳しい人物として知られています。ツールはオープンソースで公開されており、オフライン環境でも動作するため、シードフレーズの検証によく利用されています。
Mnemonic Code Converterにエントロピーを入れて完了

上図にもありましが、以下のようにすることでシードフレーズが出力されます。

  • 「Show entropy details」をクリック
  • 「Entropy」にペースト

SeedSignerの出力と一致していればクロスチェック完了です。これで、使用したSeedSignerのサイコロ乱数を用いたシードフレーズ生成機能は問題がないことを確認できました。

cable exclude they twice sugar delay exist female improve beauty bring betray awful vivid beyond cool rib napkin melody traffic taxi glue market tiny

簡易クロスチェック(SeedSigner用)

上記のサイコロ乱数クロスチェックの場合、以下のような懸念があります。

  • サイコロ乱数の打ち間違いが起きる
  • 時間がかかって面倒である(例えばファームウェアアップデートのたび確認するのが億劫)

SeedSignerであればさらに簡単にクロスチェックする方法があります。それはサイコロを振らずに入力する方法です。

💡
Coldcardではランダム性の低い入力ではシードフレーズ出力ができないので同様にはできません。シードフレーズ出力前の小さく表示されるSHA256の出力値を確認することが可能ですが、その通りにシードフレーズが出力されることは確認できません。

例えばSeedSignerのサイコロ乱数ですべて「1」を入力します。

111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

同様にWebアプリでクロスチェックすると、シードフレーズが一致することを確認できます。

[SHA256出力値]
fa098eb852b2660348b21bb00ad03a49cc177ea07ebe34f46b40baa85313525e

[24単語]
wheel erase puppy pistol chapter accuse carpet drop quote final attend near scrap satisfy limit style crunch person south inspire lunch meadow enact tattoo

すべて同じ数字であれば打ち間違いも起きにくく、時短になります。

不安であればすべて「6」にしたり、50個は「1」49個は「2」などアレンジしてチェックが可能です。個人的には簡易クロスチェックで十分だと思います。

ハイレベル検証:Mnemonic Code Converterを使わない

先ほど紹介した「簡易クロスチェック」とは異なり、ハイレベル検証はより時間がかかります。一方で、Mnemonic Code Converterというサイトを使わずにクロスチェックが可能となります。

具体的には「③Webアプリでシードフレーズが一致するかクロスチェック」のSHA256(Text)までは同様で、自分の手で01の塊をシードフレーズに割り当てていきます。

まずはサイコロ乱数をもとにSHA256(Text)の出力値を用意します。

[サイコロ乱数]
346314616632343521235326436331312443521254515431641554542166543251122545154245653432165642544226231

[SHA256(Text)出力値]
1fe9df8275ad8c73d3f2a7720274708ab10bea45717eb8f25e2a736de6c7e20f

次に、出力値の16進数を2進数に変換します。Web上の変換サイトやTerminalを使用してもいいですし、手作業で1つずつ2進数変換しても問題ありません。

1111111101001110111111000001001110101101011011000110001110011110100111111001010100111011100100000001001110100011100001000101010110001000010111110101001000101011100010111111010111000111100100101111000101010011100110110110111100110110001111110001000001111(253文字)

ここで注意点として、冒頭の「0」が表示されていないことがあります。そのため、文字数を数えて256未満であれば、256文字になるように0を追加します。

0001111111101001110111111000001001110101101011011000110001110011110100111111001010100111011100100000001001110100011100001000101010110001000010111110101001000101011100010111111010111000111100100101111000101010011100110110110111100110110001111110001000001111(256文字)

次にチェックサムの頭8桁分を用意します。SHA256(Text)出力値「1fe9df8275ad8c73d3f2a7720274708ab10bea45717eb8f25e2a736de6c7e20f」をさらにSHA256(Hex)でハッシュにかけます。TextではなくHexであることにご注意ください。

13721480e8ad790ee7c91da8b4acceaa55d33fdc7ce0df6a6813d0ff834940e2

こちら全部2進数にしてもいいですが、頭8桁だけでいいので最初の16進数「13」を2進数変換します。

13(hex)

00010011(bin)

これで必要な素材が揃いました。256桁の2進数と、8桁の2進数(チェックサム)を接続し、11桁ごとに振り分けて単語化します。

変換においてビットコイン研究所の著者の加藤規新さんが作った「Binary bits to BIP39 words」が使いやすいですが、一般的なBIP39 Word Listでも可能です。(後者の場合は0スタートではないので、1つずらすようにする点、2進数を10進数に戻す点が少し大変です)

00011111111 cable
01001110111 exclude
11100000100 they
11101011010 twice
11011000110 sugar
00111001111 delay
01001111110 exist
01010100111 female
01110010000 improve
00010011101 beauty
00011100001 bring
00010101011 betray
00010000101 awful
11110101001 vivid
00010101110 beyond
00101111110 cool
10111000111 rib
10010010111 napkin
10001010100 melody
11100110110 traffic
11011110011 taxi
01100011111 glue
10001000001 market
11100010011 tiny

図として表現すると以下のようになります。

Mnemonic Code Converterを使わない方法の全体像
作業箇所の色分け

ハイレベル検証は時間がかかり大変ですが、Mnemonic Code Converterのサイトに依存することなく、さらにシードフレーズ生成の仕組みの理解が深まります。時間があるときに自由研究的な形で一度試してみることをおすすめします。

12単語では半分の128桁が使われる

ここまで24単語で進めてきましたが、12単語の場合はSHA256(Text)出力値の冒頭の半分を使用します。結果として128bitを使用するので、12単語のエントロピーの最大値は128bitとなります。

その他の流れは同様です。

12単語の場合のシードフレーズ生成までの仕組み。左から3つ目の「頭128」が異なります

実際の検証は割愛しますが、ぜひ12単語のクロスチェックはお手元でお試しいただければと思います。

まとめ:クロスチェックして自分の乱数でシードフレーズを作ろう

サイコロ乱数は、SeedSignerやColdcardの内部で一度SHA256を通る際にブラックボックス化してしまい、実際に自分の出目が使われたかを事後的に確認することはできません。本稿で紹介したクロスチェックは、ブラックボックス化した部分をシードフレーズを実利用する前に確認しておく手順です。

やること自体はシンプルで、同じサイコロ乱数をSeedSignerとWebアプリの両方に入力し、出力されるシードフレーズを見比べるだけです。すべて「1」を入力する簡易チェックでも成立するため、サイコロを99回振る手間や打ち間違いのリスクを避けられます。

実際に使うシードフレーズには影響しない工程ですが、ファームウェア更新のたびに一度試しておけば、乱数生成部分に意図しない変更が入っていないかを継続的に確認できます。

本稿ではSeedSignerを例に解説しましたが、Coldcardでも同じ考え方でクロスチェックが可能です。サイコロ乱数でシードフレーズを作る方は、実利用の前に一度お試しください。