ブロックチェーンとハッシュ関数の数学
一方向関数と合同算術で「改ざん不可能な鎖」と「計算コストの証明」を作る仕組み
- 1
- ハッシュ関数は「任意の長さの入力を固定長の出力に圧縮するが、出力から入力を逆算するのが(計算量的に)不可能」な一方向関数であり、合同算術(mod演算)の非可逆性を土台にしている
- 2
- ブロックチェーンは各ブロックに「1つ前のブロックのハッシュ値」を埋め込むことで鎖状につながっており、途中のどれか1つのデータを書き換えると、それ以降の全ブロックのハッシュ値が芋づる式に不一致になり改ざんが即座に露見する
- 3
- 「特定のパターン(例: 先頭が0でN個続く)を満たすハッシュ値を作るnonce(使い捨ての数値)を探す」作業がProof of Work(プルーフ・オブ・ワーク)であり、答えを探すのは膨大な試行が必要だが、見つかった答えの検証は一瞬で済むという非対称性を利用している
なぜこれを学ぶのか? — 現実社会とテクノロジーでの価値
なぜ生まれたのか?
ハッシュ関数は「任意の長さの入力を固定長の出力に圧縮するが、出力から入力を逆算するのが(計算量的に)不可能」な一方向関数であり、合同算術(mod演算)の非可逆性を土台にしている
身につく武器・思考力
ブロックチェーンは各ブロックに「1つ前のブロックのハッシュ値」を埋め込むことで鎖状につながっており、途中のどれか1つのデータを書き換えると、それ以降の全ブロックのハッシュ値が芋づる式に不一致になり改ざんが即座に露見する
実社会・ITでの活躍現場
- •ブロックチェーンにおける簡易ハッシュ連鎖とProof of Work(マイニング)の実装
- •ITシステム・アルゴリズム実装における論理設計
- •データ分析やシミュレーションにおける数理モデリング
Layer 1 — 直感・シミュレーター
4つのブロックが鎖状に並んでおり、それぞれ「データ」「nonce(試行値)」「ハッシュ値(前ブロックのハッシュ+データ+nonceから計算)」を表示している。どれかのブロックの「データ」欄を書き換えてみよう。そのブロック以降のハッシュ値が即座に不一致(赤色でマーク)になり、鎖が「壊れる」様子が視覚化される。各ブロックの「マイニング」ボタンを押すと、ハッシュ値が指定パターン(先頭が0)で始まるまでnonceを自動的に総当たりで探す、Proof of Workの疑似シミュレーションを体験できる。
↑ 各ブロックのハッシュは「データ + nonce + 前ブロックのハッシュ」から計算されます(本デモは仕組み理解用の簡易チェックサム関数で、SHA-256のような実際の暗号学的ハッシュ関数ではありません)。データを書き換えるとハッシュが激変し、「マイニング条件(先頭が0で始まる)」を満たさなくなることで改ざんが視覚的にわかります。マイニングボタンはnonceを総当たりして条件を満たす値を探す、Proof of Workの疑似体験です。
ブロックチェーンにおいて、途中の1つのブロックのデータを改ざんすると何が起きるか?
Layer 2 — 定義・受験・証明
定義
ハッシュ関数 は、任意の長さのデータ を固定長の値 に写す関数であり、暗号学的ハッシュ関数は次の性質を満たすことが要求される:(1) 一方向性 — から を逆算することが計算量的に困難、(2) 衝突耐性 — となる異なる を見つけることが困難、(3) 雪崩効果 — 入力を1ビットでも変えると出力がほぼランダムに全く変化する。多くの実用ハッシュ関数の内部では、大きな数に対する合同算術(mod 演算)
の非可逆性( を法とした剰余から元の値を一意に復元できないこと)が利用されている。ブロックチェーンの各ブロック は次のように連結される。
ここで は文字列連結、 は直前のブロックのハッシュ値である。
公式・数理モデル
証明・導出
【改ざん検出可能性の証明(鎖の連鎖構造)】 ブロック のデータを から に書き換えたとする。ハッシュ関数の雪崩効果(入力のわずかな変化が出力を全く異なる値に変える性質)より、
すなわち改ざん後のブロック のハッシュ値 は元の と(確率的にほぼ確実に)一致しない。 さらにブロック は として定義されているため、 が変化した以上、ブロック の入力が変わり もまた変化する。この議論を帰納的に繰り返すと、改ざんされたブロック より後ろの全てのブロック のハッシュ値が連鎖的に不一致となる。検証者は各ブロックが「自分のデータから計算したハッシュ値」と「次のブロックが参照しているハッシュ値」を比較するだけで、この不一致(改ざん)を機械的に検出できる。
【Proof of Workの非対称性(探索困難・検証容易性)】 条件「 の値がある閾値 より小さい(先頭に ビットの が並ぶ)」を満たす を見つける問題を考える。ハッシュ関数は出力が一様ランダムに分布するとみなせるため(ランダムオラクルモデル)、ある1つの を試したときにこの条件を満たす確率は 程度である。ハッシュ関数の一方向性より、条件を満たす を効率的に「逆算」する方法は知られておらず、平均 回程度の試行(総当たり)が必要になる。一方、見つかった が本当に条件を満たすかどうかは を1回計算するだけで即座に検証できる。この「探すのは指数関数的に大変だが、答え合わせは一瞬」という非対称性が、計算資源を消費したことの証明(Proof of Work)として機能する数学的根拠である。
押さえておきたいポイント
- 本教材の疑似ハッシュ関数は説明のための簡略化されたチェックサム関数であり、SHA-256のような実際の暗号学的ハッシュ関数の安全性(衝突耐性・原像計算困難性)は持たない点に注意
- 実務のブロックチェーン(Bitcoinなど)ではSHA-256のような暗号学的ハッシュ関数が使われ、(先頭に並ぶ0ビットの数)が「採掘難易度(difficulty)」を表す
- ハッシュ関数の一方向性は、公開鍵暗号(RSA)の素因数分解の困難性とは異なる数学的困難性(合同算術の非可逆性・衝突発見の困難性)に基づく
- この「小さな変更が全体に連鎖的に伝播する」構造と検証の非対称性が、中央管理者なしで改ざんを検出できる分散台帳技術の数学的基盤になっている
本トピックの内容・数理モデルは、文部科学省学習指導要領(算数・数学・情報)および国際標準カリキュラムに準拠し、エンジニアリング現場の実装事例と照らし合わせてMath World Lab編集部により検証・作成されています。
Layer 3 — 工学応用・現場実装
ブロックチェーンにおける簡易ハッシュ連鎖とProof of Work(マイニング)の実装
教育目的の簡略化されたチェックサム式ハッシュ関数を用いて、データ・nonce・前ブロックのハッシュ値から各ブロックのハッシュ値を計算し、鎖の整合性検証とnonce総当たりによるマイニング(Proof of Work)を行うTypeScript実装。実際の暗号通貨ではSHA-256など暗号学的に安全なハッシュ関数が使われる点に注意。
1interface Block {2 index: number;3 data: string;4 nonce: number;5 previousHash: string;6 hash: string;7}89// 教育目的の簡易ハッシュ関数(実運用のSHA-256等の代わりに、仕組み理解用のチェックサム)10function simpleHash(input: string): string {11 let hash = 0;12 for (let i = 0; i < input.length; i++) {13 hash = (hash * 31 + input.charCodeAt(i)) % 1_000_000_007; // mod演算で固定範囲に圧縮14 }15 return hash.toString(16).padStart(8, "0");16}1718function computeBlockHash(block: Omit<Block, "hash">): string {19 return simpleHash("" + block.index + block.data + block.nonce + block.previousHash);20}2122// 先頭が指定パターン(例: "0")で始まるハッシュを見つけるまでnonceを総当たり探索23function mineBlock(block: Omit<Block, "hash" | "nonce">, difficulty: number): Block {24 let nonce = 0;25 let hash = "";26 const target = "0".repeat(difficulty);2728 do {29 nonce++;30 hash = computeBlockHash({ ...block, nonce });31 } while (!hash.startsWith(target));3233 return { ...block, nonce, hash };34}3536// チェーン全体の整合性を検証(前ブロックとのハッシュ連鎖をチェック)37function isChainValid(chain: Block[]): boolean {38 for (let i = 1; i < chain.length; i++) {39 const current = chain[i];40 const previous = chain[i - 1];41 if (current.previousHash !== previous.hash) return false; // 連鎖切れ42 if (computeBlockHash(current) !== current.hash) return false; // データ改ざん43 }44 return true;45}4647// 例: 2ブロックの簡易チェーンを構築し、改ざんを検出する48const genesis = mineBlock({ index: 0, data: "genesis", previousHash: "00000000" }, 2);49const second = mineBlock({ index: 1, data: "Alice pays Bob 10 coins", previousHash: genesis.hash }, 2);50const chain = [genesis, second];5152console.log("チェーンは正常か?", isChainValid(chain)); // true5354chain[0].data = "Alice pays Bob 9999 coins"; // 改ざん55console.log("改ざん後、チェーンは正常か?", isChainValid(chain)); // false
次に学ぶならコレ!おすすめトピック
この単元と深い繋がりを持つ、あわせて学ぶと理解が深まるおすすめ単元