iT邦幫忙

0

Day 16:不安全的隨機數(為什麼 block.timestamp 不可信)

  • 分享至 

  • xImage
  •  

許多 DApp(抽獎、NFT mint、遊戲)會需要隨機數。但在區塊鏈上「看起來隨機」的值(像 block.timestamp、blockhash)其實並非真隨機,可能被礦工或驗證者操控一點點,足以讓攻擊者獲利。今天我們解釋為什麼鏈上隨機性不可信、攻擊向量,以及實務上更安全的替代方案(例如 Chainlink VRF 與 commit–reveal)。

  1. 鏈上變數不是不可控的亂數來源:block.timestamp/blockhash 能被礦工或驗證者在一定程度操控。
  2. 攻擊向量:礦工可選擇包含或延遲某交易、調整 timestamp、或用重排(reorg)來影響結果。
  3. 較安全替代:使用外部經審計的 VRF(如 Chainlink VRF)、commit–reveal 或閾值簽章(threshold signatures)等設計。

🔍 為何 block.timestamp / blockhash 不可信?

  1. 礦工/驗證者可以操控時間(timestamp)
    • 區塊時間由打包區塊的礦工/驗證者設定,雖然節點會有合理範圍限制(不能隨意天馬行空的時間),但礦工可以在允許範圍內微調數秒到數十秒,足以改變 % 運算等簡單亂數公式的結果。
    • 在高利益場景(例如大量獎金)這些秒數就是攻擊者的利潤來源。

  2. blockhash 與 recent block 的可預測性
    • blockhash 通常只能取得最近 N 個區塊的雜湊(例如 Ethereum 限制),且當前區塊在被打包前也可能被前一個礦工預測或影響。
    • 如果隨機數依賴可被觀察到或提前影響的值,攻擊者可在 mempool 觀察/操控交易來布局套利策略。

  3. 重排(Reorg)或自挖(Self-mining)
    • 若攻擊者有部分算力或做得成 validator collusion,可能透過重排或自己打出特定區塊來改變隨機來源結果(雖然成本較高,但對高價值獎勵可能還是划算)。

⚠️ 攻擊向量示例(簡化)
• 抽獎合約 winner = uint(keccak256(block.timestamp, msg.sender)) % N:礦工能調整 timestamp 使自己或合作夥伴成為中獎者。
• NFT mint 階段:觀察 mempool,先發高優先費交易或延遲交易以影響 blockhash 計算結果,達到搶到稀有屬性。

✅ 較安全的替代方案(與示意)

  1. Commit–Reveal(提交-揭示)
    • 流程:參與者先 commit = keccak256(secret) 上鏈;在揭示階段 reveal secret,合約用 reveal 與 commit 驗證後匯總成亂數。
    • 優點:防止在 mempool 階段被觀察到即時操控。
    • 缺點:需要兩階段互動,若參與者不 reveal 可能需要罰則或懲罰機制(複雜化設計)。

commitPhase: submit keccak256(secret)
revealPhase: submit secret -> require(hash(secret) == commit)
finalRandom = keccak256(seedFromAllReveals)

  1. 外部 VRF(範例:Chainlink VRF)
    • 概念:把隨機數的產生交給受信任且可驗證的外部服務(Verifiable Random Function)。
    • 優點:提供不可預測且可驗證的隨機值,且攻擊成本高。Chainlink VRF 會返回一個 proof,可在合約端驗證。
    • 缺點:依賴第三方(但已是去中心化且廣泛使用的 service),有費用與延遲。

requestRandomness() -> VRF node generates random + proof -> callback fulfillRandomness(random, proof) -> contract verifies & uses random

  1. 區塊鏈協議層(Beacon / Randao / Threshold Sig)
    • Beacon / Randao:一些鏈(或 layer2)提供協議層隨機(例如以太坊 Beacon 隨機性),或使用多方提交累加(Randao)。
    • Threshold signatures / DKG:多方閾值簽章系統由多個參與者共同產生不可預測的隨機值,攻擊者需控制閾值以上的參與者才有影響力。
    • 優缺點:安全性好但實作複雜,通常適合高價值或需要強安全保證的場景。

🛡️ 實務設計建議(checklist)
• 不要用 block.timestamp、block.difficulty、blockhash(近期)做為唯一隨機來源。
• 若是低價值或娛樂用途,blockhash + user-provided entropy 可能「足夠」,但明確告知風險。
• 若需高安全性:使用 Chainlink VRF 或其它已驗證的外部 VRF。
• 若希望去中心化且不用第三方:採 commit–reveal 並設計懲罰/保證機制,或採用 threshold randomness。
• 在白皮書與合約 README 清楚說明隨機性來源與風險,讓使用者知情同意。

在鏈上「看似隨機」的東西往往是最容易被利用的。以前我也常用 block.timestamp % n 當作快速做法,但做過幾次模擬後就發現:當獎金夠大時,總有人願意花點成本去操控結果。
實務上,選擇哪種隨機性解決方案是一個折衷(安全 vs 成本 vs 便利)。如果你的遊戲或抽獎涉及實際金錢,請務必把隨機來源當成頭等大事來設計,而不是臨時寫幾行算式就交差了。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言