技術安全 · 7 分鐘閱讀

正確的產生器,
正確的語言

並非所有密碼產生器都一樣。你的保險庫由哪種語言撰寫,也絕不是只有工程師才需要在意的細節。本文解析熵、產生模式,以及為什麼 Rust 正在成為底層安全的關鍵選擇。

發布於 2026 年 6 月 · 閱讀時間 7 分鐘

當密碼管理器聲稱「產生強密碼」時,有兩個問題必須回答:它真的不可預測嗎(隨機性的品質),以及顯示之後它在記憶體中會發生什麼?前者取決於產生模式,後者取決於執行應用程式的語言。本文會同時說明這兩點。

~100 bits
16 字元隨機密碼(非常強)
~77 bits
6 個單字的 Diceware 通關短語(EFF)
12,9 bits
每個 Diceware 單字增加的熵(7,776 詞表)

01 / 基礎熵:唯一真正重要的指標

密碼強度不應按主觀感受中的「複雜度」衡量,而應按衡量:也就是攻擊者面對的不確定性位元數。可能組合越多,暴力破解成本就越呈爆炸式成長。一個從完整 ASCII 字元集中隨機抽取的 16 字元密碼約有 100 bits 熵,屬於「非常強」的範疇。

一個經常被忽略的關鍵點是:只有當隨機來源是 CSPRNG(加密安全偽隨機數產生器)時,熵才有意義。一般的 Math.random() 是可預測的,會讓其餘設計全部失效。優秀實作會從作業系統讀取熵:Unix 下的 /dev/urandom 或 getrandom(2),Windows 下的 CNG。

02 / 模式四類產生器

優秀的管理器不應只提供「一個」產生器,而應提供多種適配不同用途的模式。規則很簡單:可記憶性要用長度來換。下面是四類方式,從最高密度到最貼近人類記憶依序排列。

純隨機

j7$kQ!mP2#xR9vL@
~100 bits,16 字元
每個字元的資訊密度最高。適合存放在保險庫中的帳戶密碼,也就是從不需要憑記憶輸入的密碼。預設應優先使用這種模式。

通關短語(Diceware / EFF)

Granite-Bicycle-Phantom-Violet-9
~77 bits,6 個單字
從 7,776 個單字的詞表中隨機抽取。畫面上看起來更長,但幾秒鐘內就能記住。這是主密碼的理想選擇,因為它絕不應該被寫在別處。

可記憶 / 可發音

Crimson7!Falcon$Reef
中等熵
採用「單字-數字-符號」的模式,更容易大聲讀出,也更適合在手機上輸入。這是一種可接受的折衷,但在長度相同的情況下熵更低:如果目標是可記憶性,通關短語仍然更好。

數字 PIN

8392 4471
較低,僅限特定用途
僅適用於只接受數字的場景。除受限環境外,應避免使用。

正確習慣:讓熵匹配用途

對於受登入頁面限速保護的 Web 帳戶,攻擊者通常被限制在每秒幾百次嘗試以內:即使 50 bits 也足以支撐極其漫長的破解時間。超高熵只對離線機密有意義,例如加密金鑰或加密錢包 seed,因為這類攻擊可以被大規模平行化。 對於這些極高價值的機密,使用真實物理骰子(嚴格意義上的 Diceware)仍然是終極選擇:它消除了對 CSPRNG 品質或遭攻陷瀏覽器的任何依賴。

03 / 底層機制為什麼 Rust 改變了局面

產生一個好密碼只是工作的一半。另一半是:不要讓它在記憶體中游蕩。密碼一旦顯示或解密,就會存在於 RAM 中,而這正是應用程式所用語言變得決定性的地方。

Microsoft 報告指出,其遇到的安全漏洞中有 70% 是記憶體 bug(buffer overflow、use-after-free 等)。Google 在 Chrome 和 Android 上也觀察到相同比例。Rust 透過所有權模型(ownership)與借用模型(borrowing),在編譯期消除了這些漏洞類別,而且不需要垃圾回收器。

Google 的資料很有說服力:Android 的記憶體漏洞從 2019 年的 223 個降至 2024 年的不到 50 個,首次跌破總漏洞數的 20%。新的 Rust 程式碼相較歷史 C/C++ 程式碼,記憶體漏洞密度最高可降低 1000 倍,同時 rollback 減少 4 倍,程式碼審查時間減少 25%。

1. 沒有垃圾回收器的記憶體安全。 Java 或 Python 等語言同樣具備記憶體安全性,但它們的 garbage collector 會以非確定性的方式釋放記憶體:秘密可能無限期殘留其中,暴露在 memory dump 或 cold-boot 攻擊之下。Rust 會在資料不再使用時確定性地釋放記憶體。

2. 使用 zeroize 明確抹除。 Rust 並不保證已釋放記憶體會被覆寫。zeroize crate 補上了這個缺口:把秘密包裝在 Zeroizing 中,就能保證它在離開作用域的確切時刻被零覆寫,這透過編譯器無法最佳化掉的 volatile 寫入實現。

3. 強制正確使用密碼學的型別系統。 Rust 嚴格的型別系統可以限定敏感資料如何被使用,以及能被使用多少次。例如,可以建模一把只能使用一次的金鑰,編譯器會拒絕任何重複使用。

自動記憶體抹除use zeroize::Zeroizing;

fn unlock_vault(master: &str) {
    let dek = Zeroizing::new(derive_key(master));
    // ... 解密保險庫 ...
}   // `dek` 會在此處自動被零覆寫
在 Google,採用 Rust 後,Android 記憶體漏洞占比從 76%(2019)降至 24%(2024),遠低於業界常見水準(~70%)。

技術上要誠實:Rust 不是魔法棒

unsafe 程式碼和第三方依賴仍然是攻擊面。Google 就曾在投產前修復過 Rust 解析器中一個 unsafe 程式碼區塊裡的漏洞(CVE-2025-48530)。記憶體安全是一防護,而不是終點:它必須與縱深防禦結合,例如 Argon2id 等強健 KDF、zero-knowledge 架構、自動鎖定和 MFA。

垃圾回收語言

  • 記憶體釋放時間不確定
  • 秘密會在記憶體中殘留未知時長
  • 明確抹除困難或不可行
  • 暴露於 dump 與 cold-boot 攻擊

Rust

  • 確定性釋放(ownership)
  • 透過 zeroize 立即抹除
  • 沒有 buffer overflow 或 use-after-free
  • 密碼學使用錯誤在編譯期被捕獲

04 / 要點你應向密碼管理器提出的要求

在選擇或評估密碼管理器時,可以直接問四個具體問題:

檢查清單

  • 1. 產生器是否基於系統 CSPRNG,並以 bits 顯示熵?
  • 2. 是否為主密碼提供 Diceware/EFF 通關短語模式
  • 3. 產生過程是否本機執行(client-side),不會經過伺服器?
  • 4. 敏感核心是否用記憶體安全語言撰寫,並明確抹除秘密?

本文為教學性質的資訊內容。引用的統計資料(Google/Android、Microsoft、Diceware/EFF)來自上方列出的來源。Rust 程式碼範例僅用於說明,並經過簡化。

安全的產生方式。為長久使用而設計的保險庫。

高熵密碼、可記憶通關短語,以及為記憶體安全打造的核心。

了解我們的方法