「サイコロの出目を透視する泥棒」を防ぐ!スマートコントラクトの乱数生成の罠
こんにちは。セキュリティの世界へようこそ!
今日は、ブロックチェーン開発で「絶対にやってはいけないこと」の中でも、特に多くの初心者が陥りやすい「予測可能な乱数」という落とし穴についてお話しします。
「ブロックチェーンって改ざんできないから、何でも安全なんでしょ?」と思っていませんか?実は、仕組みをよく理解せずにコードを書くと、まるで「鍵がガムテープで留められた玄関」のような状態になってしまうんです。
—
なぜ「ブロックハッシュ」を乱数に使ってはいけないのか?
スマートコントラクトでゲームや抽選プログラムを作るとき、「ランダムな数字が欲しいな」と考えて、ついこんなコードを書いてしまう人がいます。
// 警告:絶対にやってはいけない例です!
function drawWinner() public view returns (uint256) {
// ブロックのハッシュ値を使って乱数を作る
uint256 randomNum = uint256(blockhash(block.number - 1));
return randomNum % 100;
}
一見、複雑そうで難解な数字に見えますよね。でも、攻撃者から見れば、これは「家の鍵を道端に落としておく」のと同じくらい危険なことなんです。
なぜ危険なのか?(泥棒の視点)
blockhash はブロックチェーンの履歴の一部です。ブロックが生成された瞬間にその値は確定し、誰でも見ることができます。
もしあなたが「くじ引き」を主催したとして、攻撃者はこんなズルをします。
1. blockhash が決まる直前に、プログラムの動きを先読みする。
2. もし自分に不利な結果になりそうなら、そのトランザクション(取引)をわざと失敗させるか、自分が勝てるブロックになるまで待ち伏せする。
これは、サイコロを振る前に相手が「どの目が出るか」を知っていて、自分の都合が悪いときだけサイコロを投げ直しているようなものですね。
—
一歩ずつ対策を学んでいきましょう!「Chainlink VRF」という解決策
では、どうすれば公平なサイコロが振れるのでしょうか?
ここで登場するのが「Chainlink VRF (Verifiable Random Function)」という仕組みです。
これは、「ブロックチェーンの外」にいる信頼できる第三者(オラクル)に、証明書付きのランダムな数字を持ってきてもらう方法です。
防犯の仕組みに例えると…
自分でサイコロを振って「ほら、6が出たよ!」と言うのではなく、「第三者機関が発行した、改ざん不可能な乱数証明書」を提出してもらうイメージです。これなら、誰もズルはできませんよね。
—
安全な乱数生成の実装例
Chainlink VRFを使うと、コードは少しだけ複雑になりますが、セキュリティは段違いに強固になります。以下のような流れで実装します。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";
contract FairLottery is VRFConsumerBaseV2 {
// 乱数生成を要求した後の処理
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
// randomWords[0] に安全な乱数が入ってくる
uint256 winningNumber = randomWords[0] % 100;
// ここで当選処理を行う
emit WinnerDetermined(winningNumber);
}
// 実際の開発では、ChainlinkのサブスクリプションIDなどを設定します
// これにより、誰にも予測できない真の乱数が手に入ります
}
- 重要なポイント:
VRFConsumerBaseV2を継承し、Chainlinkのノード経由で乱数を受け取る。fulfillRandomWordsという関数で、結果が返ってきた後の処理を分離する。- これにより、誰かがサイコロを操作する余地を物理的にシャットアウトします。
—
今日のまとめ:セキュリティは「透明性」と「信頼」
ブロックチェーンの世界では、「見えているデータ」をそのまま乱数源にしてはいけません。
1. 盲点を突く: blockhash や timestamp は、みんなが見ている公開情報です。それを秘密の乱数として使うのは、泥棒に暗証番号を教えるのと同じです。
2. 第三者を活用する: Chainlink VRF のような、数学的に証明可能な仕組みを使うのが現代の標準です。
3. 初心者の心構え: 「動けばいい」ではなく「誰がどうやってズルをしようとするか?」を考えるのが、セキュリティリサーチャーへの第一歩です。
最初は難しく感じるかもしれませんが、こうして一つずつ「泥棒の入る隙間」を埋めていくことが、あなたのコードを世界一堅牢にする近道です。
さあ、次はどんな「盲点」を見つけて対策していきましょうか?また次の記事でお会いしましょう!
コメント