電腦產生的隨機數分為**偽隨機** (演算法產生、可重現) 與**密碼學安全隨機** (熵源驅動、不可預測)。選擇錯誤的類別可能導致安全漏洞或高併發下重複值。
var rd = new Random();
int n = rd.Next(); // 0 ~ Int32.MaxValue
int range = rd.Next(1, 100); // 1 ~ 99
原理:以 Environment.TickCount (系統啟動毫秒數) 為種子。
// 短時間內多次 new Random() 會產生相同種子 → 相同序列
for (int i = 0; i < 10; i++)
{
var r = new Random();
Console.WriteLine(r.Next()); // 輸出 10 個相同數字
}
解法:共用單一 Random 實例 (注意執行緒不安全) 或改用 ThreadLocal<Random>。
string guid = Guid.NewGuid().ToString(); // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
string compact = Guid.NewGuid().ToString("N"); // 32 位十六進位無分隔
特性:128 位整數,結合 MAC 位址、時間戳記、時鐘序列,極低機率碰撞。
適用:訂單號、資料庫主鍵、分散式系統唯一標識。**不適用**需數值運算或固定長度數字場景。
using (var rng = new RNGCryptoServiceProvider())
{
byte[] bytes = new byte[16]; // 128 bits
rng.GetBytes(bytes);
string hex = BitConverter.ToString(bytes).Replace("-", "");
// 或轉為整數
int secureInt = BitConverter.ToInt32(bytes, 0);
}
優勢:使用作業系統熵池 (Windows: CryptGenRandom / Linux: /dev/urandom),高併發下極難重複。
代價:效能較 Random 低 10~100 倍,大量迴圈中會明顯拖慢效能。
// 需引用 System.Web.Security
string pwd = Membership.GeneratePassword(length: 20, numberOfNonAlphanumericCharacters: 2);
// 輸出範例: "C!&^HoTNv3!ZHkK9BAbu"
內部同樣使用 CSPRNG,適合產生符合密碼策略的隨機字串。
| 場景 | 推薦類別 | 理由 |
|---|---|---|
| 遊戲骰子、測試資料、非安全業務邏輯 | Random (單例/ThreadLocal) | 效能最佳、API 簡單 |
| 資料庫 PK、分散式追蹤 ID、檔案命名 | Guid | 全域唯一、無需協調 |
| 加密金鑰、Token、重設密碼連結、OAuth state | RNGCryptoServiceProvider / RandomNumberGenerator | 密碼學安全、抗預測 |
| 使用者可閱讀的隨機密碼 | Membership.GeneratePassword | 內建字元集與複雜度控制 |
// 統一介面 RandomNumberGenerator (跨平台)
using (var rng = RandomNumberGenerator.Create())
{
var bytes = new byte[32];
rng.GetBytes(bytes);
// ...
}
// 簡易取得安全隨機整數
int secureRandom = RandomNumberGenerator.GetInt32(Int32.MaxValue);