| 実験 | 検索空間 | 実現可能? | 教訓 |
|---|
weak_entropy — 弱いRNGウォレット空間を列挙 | 2³² (不良なRNG) | はい、数日で | ウォレットは、その背後にあるエントロピーと同じだけの強さしかありません。 |
blind_search — 良好な鍵空間を総当たり | 2¹⁶⁰ (優良なRNG) | いいえ、永遠に | 真のエントロピーがあれば、鍵空間は物理的に検索不可能です。 |
要点はこの対比です: 鍵は悪い乱数への攻撃によって盗まれるのであり、良い乱数を計算で凌駕することによって盗まれることは決してありません。 両方の実験は同じ種類の実際のメインネットアドレスを導出するため、唯一の変数はエントロピーです。
このリポジトリは防御的教育とセキュリティ研究を目的としています: 弱いRNGのウォレットバグ(Milk Sad / CVE-2023-39910、2018年のTrust Wallet拡張機能のバグ、およびその類)がなぜ壊滅的だったのか、そして適切に生成された鍵の総当たりがなぜ不可能なのかを理解することです。
weak_entropy は自己完結型の合成空間を列挙します。その weak_entropy() は脆弱性クラスの意図的なモデル — BIP39に供給する32ビットPRNG — であり、実際のウォレットのRNGをバイト単位で複製したものではありません。生成されるアドレスは誰の実際のウォレットにも対応しません。blind_search は自分のノードに対する読み取り専用の残高照会です。鍵を導出せず、何も送金できません。その代表的なモードは、ブラインド検索の無益さを測定します。自分が管理するウォレット、テストネット、またはサンドボックスとして使用してください。他人のお金には向けないでください。
教育および許可されたセキュリティ研究のみを目的としています。自分が所有する、または明示的な書面による許可を得てテストする鍵、ウォレット、システムにのみ使用してください。他人のウォレットやシステムへの不正アクセス、およびデジタル資産の窃取は、技術的手段に関係なく、米国CFAA(18 U.S.C. § 1030)、英国コンピュータ乱用法1990、EU指令2013/40/EUなどの法律で違法です。「現状のまま」、保証なしで提供されます。著者は悪用に対する責任を負いません。これは法的助言ではありません。完全な条件と責任ある開示の指針: DISCLAIMER.md。
ウォレットのセキュリティは、シードに投入されたエントロピーによって制約されます。下流のSHA-256 / PBKDF2 / secp256k1の強度によるものではありません。
BIP39はエントロピーをニーモニックに変換し、PBKDF2はそれをシードに引き伸ばし、BIP32は鍵のツリーを導出します。これらはすべて強力です。しかし、どれもエントロピーを追加しません — シードが小さな集合から抽出された場合、ウォレットが生成できるすべてのアドレスは列挙可能であり、どんなハッシュ化もそれを隠すことはできません。
bitcoin-security/
├── bitcoin_security/ # the package
│ ├── derivation.py # shared core: BIP39 + BIP32 + P2PKH/WIF
│ ├── data/english.txt # BIP39 English wordlist (2048 words)
│ ├── weak_entropy/ # Experiment 1 — enumerable weak space
│ │ ├── enumerate.py # recovery demo + full-space dump
│ │ └── README.md
│ └── blind_search/ # Experiment 2 — futile brute-force search
│ ├── scan.py # UTXO-set balance scanner + odds
│ └── README.md
├── tests/ # offline test suites (no node/network)
│ ├── test_blind_search_addresses.py
│ └── test_blind_search_pipeline.py
├── docs/FINDINGS.md # benchmarks + exact full-space size derivation
├── pyproject.toml
├── requirements.txt
└── LICENSE
このツリーはアイデアを反映しています: 共有のderivationコアと、同じアドレス空間について正反対の結論に達するためにそれを使用する2つの実験です。
pip install -r requirements.txt # runtime deps
# optional — installs the package + `bsec-enumerate` / `bsec-scan` commands:
pip install -e .
coincurve(ネイティブlibsecp256k1)は導出を約5倍高速化しますが、オプションです — derivation.pyは同一の出力で純Pythonのecdsaにフォールバックします。ここでネットワークに触れるのは、オプトインの--check-balanceフラグとblind_search(ローカルのBitcoinノードが必要)だけです。
すべてリポジトリルートからモジュールとして実行できます。インストールは不要です:
python3 -m bitcoin_security.weak_entropy --help
python3 -m bitcoin_security.blind_search --help
weak_entropy: 弱いエントロピーは列挙可能ウォレットの「ランダムな」BIP39エントロピー16バイトは、実際には32ビットのシードに由来します。完全な導出は本物であり、仕様ベクトルに対して検証済みです。
seed32 ──MT19937──▶ 16-byte entropy ──BIP39──▶ mnemonic ──PBKDF2(2048)──▶ 64-byte seed
│
address ◀──hash160──── pubkey ◀──BIP32 m/44'/0'/0'/0/0
# Recovery: derive a victim wallet from a weak seed, then recover its full
# mnemonic + private key knowing only the public address.
python3 -m bitcoin_security.weak_entropy
# Expand one seed into every form.
python3 -m bitcoin_security.weak_entropy --show 3571
# Materialize the whole 2**32 space to sharded, resumable files.
python3 -m bitcoin_security.weak_entropy --dump-all --out-dir space_dump --max-file-mb 1000
行は最小限(address <TAB> seed32)です。他のすべての形式はseed32の決定論的関数であり、--showでオンデマンドに再生成されるためです。ダンプはシャード単位で再開可能です(連続的で、欠落がなく、重複のないカバレッジを再現することが検証済み)。完全なフラグリファレンスはweak_entropy/README.mdにあります。
規模の警告。 完全な2³²ダンプは約196 GB(最小)または約1.05 TB(
--full)で、ネイティブバックエンドでも数日かかります —docs/FINDINGS.mdを参照してください。全体が必要になることはほぼありません。調査用に範囲を限定したスライスをダンプしてください。
blind_search: 良好な鍵は総当たりできないローカル(プルーニング可)ノードのUTXOセットに対してscantxoutset経由で動作する、実際に動作する残高スキャナです。その目的はヌル結果です: アドレス空間を盲目的に検索し、何も見つからないことを測定し、常にそうなることを示す計算を出力します。
python3 -m bitcoin_security.blind_search --odds-only # just the math, no node
python3 -m bitcoin_security.blind_search --random 200000 --odds # search 200k random addrs, then the math
python3 -m bitcoin_security.blind_search --control # verify the pipeline finds known-funded addrs
結果: 空間は2¹⁶⁰ ≈ 1.46×10⁴⁸です。約5500万のアドレスが残高を保持しているため、ランダムなアドレスが資金入りである確率は約3.8×10⁻⁴¹です。毎秒10億アドレスを処理しても、約8×10²³年待つことになります — 宇宙の年齢の約61兆倍です。ハードウェアの問題ではありません: Landauerの限界により、2¹⁶⁰まで数えるだけで太陽の残りのエネルギー出力を超えます。ノードのセットアップはblind_search/README.mdにあります。
両方の実験は同じ種類のアドレスを導出します。唯一の違いは、シードが抽出された集合のサイズです:
そのギャップ — 128ビット — がすべてを決定づけます。このクラスの実際の窃盗はすべて、このギャップの中に存在しました。
python3 tests/test_blind_search_addresses.py # BIP-173/350/380 address vectors
python3 tests/test_blind_search_pipeline.py # scan pipeline, RPC stubbed
python3 -m bitcoin_security.derivation # derivation self-test (spec vectors)
詳細、方法、マシン仕様はdocs/FINDINGS.mdにあります。
ecdsaをcoincurve(libsecp256k1)に置き換えることで、Apple M3 Maxでのウォレットあたりの導出が**3.02 ms → 0.591 ms(約5.1倍)**に短縮されました。残る下限は、0.463 ms/ウォレットのPBKDF2-HMAC-SHA512 ×2048です。seed32の桁の正確な閉形式と、測定された平均アドレス長に基づく196.3 GB最小 / 約1.05 TB --full。MIT — LICENSEを参照してください。利用条件と責任ある開示の指針: DISCLAIMER.md。報告: SECURITY.md。