產生器

從無到有的工具 —— 在你自己的裝置上。

4 個工具

這個分類裡的工具

這個網站其他每一個分類都是在轉換你已經有的東西。這一類正好相反:你帶著幾個設定進來,帶著一個原本不存在的結果離開。這個差別不是修辭。它改變了「會出什麼錯」、「該檢查什麼」,而且對這裡四個工具中的三個來說,它讓底層隨機的品質成為唯一真正重要的事。

三種「隨機」,以及你需要哪一種

「隨機」這個詞涵蓋了三種很不一樣的東西,而選錯是這整個分類裡最常見的錯誤。最底層是普通的偽隨機產生器:一個公式產出一串通得過統計檢定、但由內部狀態決定性推導出來的數。你瀏覽器裡的 Math.random 就是這一種 —— Chrome 與 Edge 用的是 xorshift128+。只要一小段連續輸出,就能還原它的內部狀態,然後把後面每一個值算出來。

上一層是密碼學安全的偽隨機產生器,由作業系統用硬體熵持續播種與再播種:時序抖動、中斷模式,以及現代處理器上一道專門取樣熱噪音的指令。這就是 crypto.getRandomValues 給你的東西,也是這一頁每一個工具用的東西。它無法從輸出被預測,而且沒有你看得到的種子 —— 因為一個你看得到的種子,就是別人也猜得到的種子。

最上層是直接讀取硬體來源,那對產生長期使用的密鑰有意義,其他場合基本上都沒有。決定誰先開始、抽出一個中獎者、產生一組你會存進密碼管理器的密碼 —— 中間那一層不是妥協,它就是正確答案;而真正的風險全部住在「它與最底層之間的那道差距」裡。

模數偏差:幾乎每個線上產生器共有的缺陷

隨機來源給你的是一個來自固定大小值池的值。要把它變成「1 到 6 之間的一個數」或「這個字元集裡的一個字元」,就得把值池折到比較少的結果數上。值池大小幾乎永遠不是結果數的整數倍,所以折疊的時候,前面幾個結果會各多拿到一個位置,出現得就比其他結果頻繁一點。這就是模數偏差,而那個標準的一行寫法 —— Math.floor(Math.random() * n) —— 就有這個問題。

影響有多大,取決於範圍相對於值池有多大。擲一顆骰子時,偏差遠低於任何人能察覺的程度;範圍一寬就變成量得出來的東西,而贏家永遠是你範圍裡最小的那幾個值。不論哪一種,它都是一個很容易移除、卻幾乎總是被留在裡面的缺陷。

解法是拒絕取樣:折疊之前先算出「最大的、能被結果數整除的值」,抽到大於或等於那個界的就丟掉重抽。被丟掉的區間極小,剩下的部分可以被完美等分,所以每個結果的機率變成「完全相同」而不是「大致相同」。這個網站上每一次隨機抽樣都是這樣做的,而隨機數產生器還會顯示即時的分布表 —— 讓這個主張變成你可以核對的東西,而不是你必須接受的東西。

為什麼「產生器放在伺服器上」是錯的形狀

對隨機類工具來說,理由很短。crypto.getRandomValues 讀的是你自己機器的熵池。把請求送去別人的電腦,多換到的是一次網路往返、一筆 log、以及一個知道結果的第三方 —— 而輸出一點也沒有變得更隨機。當結果有利害關係時,那筆 log 就是全部的問題:如果一次抽出決定誰拿到什麼,「第三方比你更早看到它」是一個該被消除的性質,不是一個該被管理的風險。

對密碼來說,這根本不是風險評估,而是定義問題。在伺服器上產生的密碼,就是被那台伺服器看過的密碼。有沒有人去看,取決於他們的意圖與安全性;有沒有被暴露,則沒有討論空間。這也是為什麼這裡的密碼工具刻意不保留任何歷史,而擲硬幣與隨機數工具刻意保留 —— 一份過去抽樣的清單讓那兩個工具可以被稽核,而一份過去密碼的清單只是純粹的風險,沒有任何好處。

QR Code 產生器是這一組裡唯一決定性的工具,所以隨機性對它無關 —— 但隱私的論點換一個形式活了下來。值得保護的是輸入而不是輸出:一個還沒發布的活動網址、一個內部儀表板、一個私人文件連結。把它貼進遠端的產生器,等於在你發布之前就先把它交給了第三方。

你要的是哪一個

如果是兩方平手要決勝、而且雙方都需要看到沒有人能影響結果,用擲硬幣。它會累積次數並把結果換算成「幾個標準差」—— 那才是真正能告訴你來源正不正常的數字;單看比例在小樣本下幾乎什麼都說不出來。

如果結果超過兩種,或你一次需要好幾個結果,用隨機數產生器。抽獎、排座位、選樂透號碼請打開「不重複」—— 那些都是抽出不放回,把它們當成彼此獨立的抽樣,運算本身就是錯的。

如果要的是一組憑證,用密碼產生器,並且讓長度去做事:熵隨長度線性成長、隨字元集大小只是對數成長,所以多一個字元換到的比多一類符號更多。如果要的是一個連結、一個 Wi-Fi 網路、或一張別人會拿相機對著掃的名片,用 QR Code 產生器 —— 而且要印刷的話請下載 SVG 而不是 PNG,因為放大的點陣圖邊緣會軟,而軟邊緣會傷害掃描成功率。

常見問題

Math.random 真的那麼糟嗎?

用在動畫、程序化繪圖、遊戲上完全沒問題。只要有人有動機事先知道結果,它就不適合 —— 因為它的內部狀態可以從一小段輸出還原,之後每一個值都算得出來。這一頁沒有任何工具用它。

可以看到或設定種子嗎?

不行。密碼學隨機來源持續混入熵,從不暴露可重現的種子,而那正是你要的性質 —— 一個看得到的種子就是一個猜得到的種子。如果你需要可重現的偽隨機來跑模擬,那是真的另一種需求。

我怎麼「查證」而不是「相信」這些隨機?

擲硬幣與隨機數工具會保留當前設定下的每一次抽樣,並顯示即時統計:距離期望中間值幾個標準差,以及切成等寬區間的分布表。你要找的是某一種型態的缺席 —— 具體來說是「最低的幾個區間持續偏高」,那是模數偏差的指紋。

這些工具有任何一個會送資料到伺服器嗎?

一個都沒有。打開開發者工具切到 Network 分頁,然後隨便用多久都可以 —— 請求清單會一直是空的。這個網站也會送出把連線限制在自己來源的 Content-Security-Policy,執行它的是你的瀏覽器,跟我們的程式怎麼寫無關。

可以離線使用嗎?

第一次造訪之後可以。頁面會被瀏覽器快取,而隨機來自你的作業系統 —— 這裡沒有任何一個環節需要網路。

依分類瀏覽