RNG 隨機數安全機制:確保博弈遊戲的公平性與合規性

從密碼學等級亂數到可驗證公平性,全面解析遊戲隨機數生成的安全設計

隨機數生成器(RNG)是博弈遊戲公平性的核心基石。本文深入說明如何使用密碼學安全的偽隨機數生成器(CSPRNG)、種子管理與熵源設計、隨機數的均勻分佈驗證,以及如何通過第三方認證機構的 RNG 審計標準。

為什麼 RNG 安全如此重要?

隨機數生成器(Random Number Generator, RNG)是博弈遊戲公平性的基石。 每一次老虎機的 Spin、每一張牌的發放、每一個骰子的結果,都取決於 RNG 產生的隨機數。 如果 RNG 存在偏差、可預測性或被操控的可能,整個遊戲的公平性就無法保證。

在合規市場中,RNG 必須通過第三方認證機構(如 GLIBMM)的嚴格審計, 確保其符合統計學上的隨機性標準。這不僅是技術要求,更是遊戲合規上線的法規門檻。

要理解 RNG 的設計取捨,必須先建立威脅模型(Threat Model)的概念。 我們假設的攻擊者並不是隨機亂試的玩家,而是一個具備完整逆向工程能力、能夠長期蒐集大量結果樣本、 甚至掌握部分程式邏輯的對手。在這個假設下,任何「因為別人猜不到所以安全」的設計都不成立; 隨機性的安全必須來自數學結構本身,而不是資訊不對稱。 這也是為什麼所有安全決策都應該建立在「攻擊者知道演算法、只是不知道金鑰與內部狀態」的前提上。

為什麼一般的偽隨機數不夠用

大多數程式語言內建的隨機函式,其設計目標是速度與統計均勻性,而不是安全性。 以常見的線性同餘產生器(LCG)為例,它的下一個狀態由當前狀態經過一次乘法與加法即可得出; 攻擊者只要觀察到少數幾個連續輸出,就能解出內部參數並完整預測未來的整個序列。 即使是統計品質相當優秀的 Mersenne Twister,也只需要蒐集約數百個連續輸出, 就能還原出完整的內部狀態並反推整條序列。

關鍵在於:通過統計檢定不等於不可預測。 一個序列可以在卡方檢定、Runs Test 上表現完美,卻仍然是完全可預測的。 統計均勻性衡量的是「輸出看起來像不像隨機」,而密碼學安全衡量的是「知道歷史輸出後能否推導未來」, 這是兩個獨立的性質。博弈遊戲同時需要兩者,缺一不可。

密碼學安全的偽隨機數生成器(CSPRNG)

博弈遊戲的 RNG 必須使用密碼學安全的偽隨機數生成器(Cryptographically Secure PRNG), 而非一般程式語言提供的標準隨機函式。兩者的關鍵差異在於:

在實作上,我們採用作業系統提供的密碼學隨機來源(在 Linux 上即 getrandom() 這類系統呼叫, 在其他平台則是對應的核心隨機介面)作為隨機數的底層來源,確保每個隨機數都具備密碼學等級的安全性。 不自行實作演算法、盡量把信任邊界推向作業系統與硬體,本身就是一項重要的安全設計原則: 核心的隨機子系統經過大量公開審查與長期實戰驗證,遠比任何自製的替代方案可靠。

熵源的取得與品質評估

CSPRNG 只是把少量真隨機「延展」成大量不可預測的位元,它本身不創造隨機性。 真正的隨機性來自熵源(Entropy Source),也就是物理上不可預測的事件。 現代作業系統會從多個獨立通道持續收集熵:CPU 的硬體隨機指令、中斷發生的時間抖動、 磁碟與網路 I/O 的完成時間、以及各種難以被外部觀測的微觀時序差異。 這些原始樣本會先進入熵池,經過雜湊混合後才對外提供。

評估熵源品質時,真正該看的指標是最小熵(Min-Entropy), 也就是「最可能出現的那個值的出現機率」所對應的熵值,而不是平均意義上的夏農熵。 這是保守估計:因為攻擊者猜測時一定優先猜最可能的值。相關評估方法在 NIST SP 800-90B 中有完整定義,包含獨立同分佈檢驗與一系列最小熵估計器。

實務上有幾個容易被忽略的熵源風險,值得在設計階段就納入考量:

消除模數偏差:Rejection Sampling

當我們需要一個範圍在 [0, max) 的隨機整數時,最直覺的做法是 rand() % max。 然而,這個做法會產生模數偏差(Modulo Bias):當隨機數的上限不能被 max 整除時, 某些結果的出現機率會略高於其他結果。

偏差的數學成因其實很直觀。假設底層隨機數的取值範圍是 0N-1 共 N 個等機率的值, 而我們想要映射到 0max-1。如果 N 不能被 max 整除, 那麼 N 除以 max 會餘下 r = N mod max 個「多出來」的值, 這些多餘的值會被分配給前 r 個結果。於是前 r 個結果各自對應 ⌊N/max⌋ + 1 個原始值,其餘結果只對應 ⌊N/max⌋ 個, 前者的出現機率因此系統性地偏高。

用一個極端的小例子最容易看清楚:若原始隨機數只有 0~9 十種可能,要映射到三個結果, 10 除以 3 商 3 餘 1,於是多出來的那一個值落給結果 0:它對應到 0、3、6、9 四個原始值, 機率是 4/10,而結果 1 與結果 2 各只對應三個值,機率都是 3/10。 這種偏差不會隨著取樣次數增加而消失,反而會在大樣本下被統計檢定精準地捕捉出來。

模數偏差示意圖 十個等機率的原始隨機數取模三之後,結果 0 拿到四個值,結果 1 與結果 2 各拿到三個值。 原始隨機數 0 ~ 9,每個值機率相同 0 1 2 3 4 5 6 7 8 9 ↓ 取 value % 3 結果 0 4/10 結果 1 3/10 結果 2 3/10
十個等機率的值映射到三個結果時,10 除以 3 餘 1,多出來的那一個值落給結果 0,於是它的機率比另外兩個高出三分之一。

雖然在 max 遠小於隨機數範圍時偏差極小,但在博弈遊戲中,任何統計上的不均勻都可能成為審計風險。 更重要的是,這種偏差是結構性而非隨機性的:它有明確方向、可被累積、也可被逆向推導利用。 因此我們採用 Rejection Sampling(拒絕採樣)來完全消除偏差:

threshold = MaxUint64 - (MaxUint64 % max)
do {
  value = crypto_rand_uint64()
} while (value >= threshold)
result = value % max

這個演算法的原理是:丟棄會造成偏差的那些隨機數(落在不完整的最後一個 max 區間的值), 只保留能產生完美均勻分佈的結果。被拒絕的機率極低(小於 max / 2^64), 對效能幾乎沒有影響,但確保了數學上完美的均勻分佈

種子管理與防碰撞

在高併發的遊戲伺服器中,RNG 的種子(Seed)管理是另一個關鍵安全點。 如果兩個玩家的 RNG 使用相同的種子,就會產生相同的遊戲結果序列。

為了防止種子碰撞,我們採用以下策略:

更完整的思路是把種子視為一個有生命週期的敏感資產,而不是一個一次性的初始化參數。 這個生命週期大致可以分為四個階段,每個階段各有必須守住的原則:

這裡有一個容易被誤解的重點:種子不可預測,不等於種子不可重複。 高併發環境下,兩個實例即使各自的種子都來自良好的熵源,仍有極小機率碰撞。 因此除了品質保證之外,還需要結構性的唯一性保證。這正是原子遞增計數器參與種子混合的用意: 它不提供隨機性,但提供了確定性的不重複保證,與熵源的不可預測性形成互補。

RNG 審計追蹤(Audit Trail)

合規要求每一個 RNG 呼叫都必須可追蹤、可重播。在我們的系統中, 每次 RNG 產生的隨機數都會被記錄到審計日誌中:

這個機制不僅滿足合規要求,也是 QA 測試的重要工具:透過注入預定義的隨機數序列, 可以進行精確的確定性測試,覆蓋所有邊界條件。

審計軌跡真正的價值在於可回溯性:當爭議發生時,能不能重建當時的完整因果鏈。 要達成這一點,記錄的欄位必須足以在事後獨立還原結果,而不需要依賴任何當時的執行環境。 實務上,一筆具備完整回溯能力的記錄至少需要涵蓋以下幾類資訊:

設計時的原則是只記錄可重現結果所需的資訊,不記錄內部狀態。 審計日誌必須詳盡到足以驗證公平性,同時又不能詳盡到洩漏 RNG 的內部狀態。 這兩個要求之間的界線,正是審計軌跡設計最需要斟酌的地方。

防止客戶端操控

RNG 安全的另一個關鍵維度是確保客戶端無法影響隨機結果。 這裡的設計原則非常明確:客戶端是不可信任的執行環境。 所有在玩家裝置上執行的程式碼都可以被反編譯、被修改、被重放; 所有從客戶端送來的資料都應該被視為攻擊者可以任意構造的輸入。 因此正確的架構不是「驗證客戶端沒有作弊」,而是「讓客戶端在結果的計算路徑上完全沒有發言權」。 客戶端只負責呈現伺服器已經決定好的結果,動畫與音效的播放順序不參與任何判定。

基於這個前提,我們的安全審計框架涵蓋以下檢查點:

GLI / BMM 認證標準

通過 GLI-19(互動式博弈系統技術標準)或 BMM 認證, RNG 需要滿足以下統計學測試:

理解這些檢定的角色定位同樣重要。統計檢定的本質是否證而非證明: 它能告訴你某個序列明顯不像隨機的,卻永遠無法證明某個序列一定是隨機的。 通過整套檢定只代表「找不到偏離隨機假設的證據」,而不代表 RNG 安全無虞。 前面提過的那些可預測產生器,同樣能輕鬆通過絕大多數統計檢定。

另外一個實務上常見的誤區,是把檢定結果當成二元的通過或失敗。 在顯著水準 α 之下,即使 RNG 完全正常,每執行一百次檢定也預期會有約 α 比例的檢定「意外失敗」。 因此正確的判讀方式是觀察 p 值本身的分佈:在虛無假設成立時, p 值應該均勻分佈於 0 到 1 之間。若某項檢定的 p 值持續集中在極端區域, 那才是真正的警訊;反之,偶發的單次失敗屬於預期內的隨機現象, 過度反應反而會導致對正常系統的錯誤判定。

我們的 RNG 實作在內部測試中持續通過所有上述測試,並定期接受第三方認證機構的獨立審計, 確保在整個產品生命週期中維持最高的隨機性標準。

分層安全架構

總結而言,我們的 RNG 安全架構分為三個層次:

RNG 分層防禦架構 三層防護由上而下分別針對外部操控、狀態污染與數學可預測性,各層假設前提不重疊。 上層 · 協議安全 客戶端隔離 / 參數驗證 / 狀態保護 防的是:來自外部的主動操控嘗試 中層 · 系統安全 種子管理 / 實例隔離 / 審計追蹤 防的是:實作與併發層面的狀態污染 底層 · 密碼學安全 CSPRNG / Rejection Sampling 防的是:數學上的可預測性與分佈偏差
三層各自針對不同性質的威脅,假設前提不重疊,因此任何一層失效時其餘兩層仍然成立。

這種多層防禦的設計確保了即使某一層出現問題,其他層仍能提供保護, 從而建立起一個穩固可靠的公平性保障體系。

分層防禦之所以有效,關鍵在於各層的失效模式互相獨立。 如果三層防護都依賴同一個假設,那麼它看似有三層,實際上仍然只有一層。 一旦那個共同假設被打破,三層會同時失守。因此在設計時, 我們刻意讓每一層針對不同性質的威脅:底層防的是數學上的可預測性與分佈偏差, 中層防的是實作與併發層面的狀態污染,上層防的是來自外部的主動操控嘗試。 三者的假設前提不重疊,才構成真正的縱深。

最後值得強調的是,隨機性的品質是不可觀測的。 一個有缺陷的 RNG 在單局結果上看不出任何異樣,只有在大量樣本的統計分佈中才會顯露。 這意味著我們無法依賴事後的人工檢視來發現問題,只能依賴設計階段的正確性、 自動化的持續統計監控,以及完整的審計軌跡三者結合。 公平性不是一個上線前檢查一次就能永久成立的性質,而是需要在整個產品生命週期中持續驗證的承諾。