本機弱密碼名單能證明什麼,為什麼它不是全網外洩查詢

檢測頁跳出「未命中弱密碼名單」,很多人會讀成「這組密碼從沒出現在任何一次拖庫裡」。這兩句差得很遠。一份隨頁下載的高頻名單,只能回答「像不像已經被用爛的密碼」;Have I Been Pwned 一類服務回答的是另一件事,查詢路徑也不同。下面把能寫進結論的句子收窄,並給出可以當場核對的步驟。

「未命中」不是「從未外洩」

弱密碼檢測給出的結果通常只有兩種:命中,或未命中。命中好理解——這串密碼已經出現在某份公開的高頻名單裡,繼續用它等於把自己放進攻擊者最先試的那一批。未命中則常被多讀一層:既然名單來自「外洩」,沒中就是「乾淨」。

名單只能對它收錄過的條目負責。一次未公開的內部外洩、一份還沒被整理進公開集合的 infostealer 日誌、你在某個小站上單獨被拖走的密碼,都不會自動出現在瀏覽器剛下載的那幾百或幾千行文字裡。未命中的完整讀法是:在目前這份本機名單、這一次比對規則下,沒有找到相同或允許的變形。它沒有對「全網」做過承諾。

把這句話寫清楚,是為了避免下一步做錯。命中時,更換是對的。未命中時,仍然要看長度、是否重複使用、是否來自密碼管理器隨機抽出。名單是過濾器,不是無罪證明。

名單防的是哪一類猜測

攻擊者很少從 a 窮舉到 zzzz…。更常見的兩條路徑是:拿已經外洩的使用者名稱和密碼去別的站試(撞庫),以及按公開弱密碼排行從前往後試(線上猜測)。123456passwordqwerty 會反覆出現在這些名單最前面,不是因為它們「看起來短」,而是因為它們被選得夠頻繁,試幾次就能碰到。

高頻名單針對的就是這一層:把已經被用濫的密碼標出來,讓你在自己還能改的時候丟掉它們。它不回答「這串字元的搜尋空間有多大」,也不回答「某個尚未公開的庫裡有沒有這一條」。後兩件事分別屬於熵估算和規模大得多的外洩語料,不該和「像不像常見弱密碼」綁成同一個結論。

這也解釋了為什麼一份並不算長的名單仍然有用。線上登入幾乎都會限流。攻擊者在被鎖之前能試的次數有限,他們會優先試排行靠前的密碼。NIST SP 800-63B-4 在 blocklist 一節寫過:名單的目的是擋住在限流耗盡前就很可能被猜中的密碼;名單大到超過這個目標之後,增量收益很小,因為線上攻擊本身已經被節流。本機高頻名單和這條目標是對齊的,它本來就不是按「收錄宇宙中每一條曾外洩的密碼」來設計的。

對台灣使用者,還有一層更容易被忽略的限制。公開討論裡常被點名的注音對照弱密碼——把中文詞用注音輸入法打成英數,看起來像亂碼、其實很好猜——在全球高頻英文、數字排行裡未必排得進前幾百名。NordPass 這類公開榜單裡,台灣前幾名仍是 1234561qaz2wsx 這類全球也常見的組合,短名單通常收得進去;在地很常見、但沒擠進全球排行的用法,就不一定。未命中只排除了這份名單裡的條目,不排除「在地很常見、但名單沒收」的弱密碼。

NIST 要求對照整串,而不是再加一套複雜度規則

美國國家標準與技術研究院在 SP 800-63B-4 裡,把「對照已知常用、可預期或已外洩的密碼」寫成驗證方必須做的步驟:建立或修改密碼時,應當把整串候選密碼拿去和 blocklist 比較,而不是看它中間有沒有某個單詞、是不是缺了符號。命中則必須拒絕,並告訴使用者為什麼被拒。

同一節還改寫了過去十幾年裡最容易被誤解的密碼政策。驗證方不得再強制「必須同時有大寫、數字和符號」這類組合規則;不得要求定期改密碼,除非有證據表明這枚認證器已經外洩;單因素密碼長度下限寫成 15 個字元,作為多因素之一時下限是 8。這些句子針對的是要接收密碼的網站,不是瀏覽器裡的自測頁。但對閱讀檢測結果的人,它們仍然有用:複雜度勾選本身證明不了安全;真正該先擋掉的,是已經出現在公開名單裡的整串。

NIST 還提醒:拒絕之後要給出換密碼的指引,避免使用者只做「password 改成 Password1」這種一眼能看穿的改寫。本機名單如果額外處理大小寫、尾部兩三位數字、常見 Leet(@ 當 a、0 當 o),針對的就是這類改寫。它仍然是啟發式,不是密碼學證明:P@ssw0rd2026! 可能被抓住,換一種沒寫進規則的變形就不會。

不要用正在使用的真實密碼做公開實驗。需要對照名單時,用已經決定廢棄的舊密碼,或一段可以丟棄的測試串。核對的是規則和流量,不是把現用密碼再暴露一遍。

本機弱密碼名單、雜湊前綴查詢、全量離線庫

「查過外洩沒有」至少有三種做法,混在一起就會把未命中讀成從未外洩。差別不在口號,在資料走了哪條路、伺服器能看見什麼。

第一種是本機短名單。頁面把一份公開文字下載到目前分頁,指令碼在記憶體裡做成集合,再拿你輸入的整串(以及少量變形)去查。出站的是名單檔本身,不是待測密碼。覆蓋面等於這份文字有多少行。以 MakePwd 隨頁提供的 leaked-top10k.txt 為例,檔名寫著 top10k,打開後可以按行數自行清點——目前是八百餘條高頻條目,不是一萬條,更不是全網。名單載入失敗時,實作會退到內建的最小集合(例如 password123456qwerty),覆蓋面更窄,檢測仍留在本機。

第二種是 Have I Been Pwned 的 Pwned Passwords 範圍查詢。官方文件把語料寫成「數以億計、曾出現在外洩中的密碼」。用戶端先在本機做 SHA-1(或 NTLM),只把雜湊的前 5 個十六進位字元發給 https://api.pwnedpasswords.com/range/{prefix},再在本機把回傳的後綴和自己算出的完整雜湊比對。明文和完整雜湊都不會按設計發給伺服端。這是 k-anonymity:5 位十六進位前綴約有 165=1,048,576 個桶,伺服器只知道你落在其中哪一個。它仍然是查詢外部介面,只是查詢的不是密碼原文。2025 年 11 月,HIBP 曾一次性納入約 13 億條不重複密碼(其中約 6.25 億條對該服務是新的);2026 年 6 月又從 stealer 日誌中加入約 1.24 億條不重複密碼。這些數字說明的是語料在膨脹,不是「查過一次就永遠乾淨」。

第三種是把整份語料下載到自己的機器或內網,完全離線比對。HIBP 也提供這種下載。覆蓋面接近第二種,但不再向 api.pwnedpasswords.com 發送前綴。代價是更新、儲存和你自己維護雜湊索引。

做法 離開本機的資料 未命中能寫成
本機高頻名單 名單檔;不應有待測密碼 不在這份名單(及已實作的變形)裡
HIBP 範圍查詢 SHA-1 / NTLM 的 5 位前綴 不在目前 Pwned Passwords 語料裡
全量離線庫 無查詢請求 不在你下載的那一版語料裡

三種說法都不能改寫成「從未出現在任何一次外洩中」。未公開的庫、尚未被收錄的日誌、你從未交給任何第三方的密碼,都不在這些集合的義務範圍內。本機名單只是其中最窄的一種,優點是待測密碼按設計不必離開分頁。

命中和未命中,各自只能寫進哪句結論

命中時,結論可以寫得很硬:這串密碼已經出現在公開高頻名單裡,或只做了名單能夠識別的改寫。繼續用它,等於把自己留在撞庫和線上猜測最先碰到的集合裡。正確動作是換掉,並且不要在其他網站重複使用同一串。

未命中時,結論必須帶範圍。它支援「不像這份名單裡的常見弱密碼」;不支援「沒被拖過庫」「可以在所有網站重複使用」「熵足夠高」。一個 20 位隨機密碼會未命中,一個只在某次未公開外洩裡出現過的密碼也會未命中。結果看起來一樣,含義不同。

還有一種「看起來很長、仍然該標弱」的情況。名單命中優先於熵:password 只有 8 個字母,按字元集估算會得到一個並不為零的位元數,但任何人都會先試它。本機檢測若在命中後把等級改成弱,依據的是名單,不是那串位元數算錯了。反過來,未命中加上很高的熵,也只說明「不像常見弱密碼,並且窮舉成本看起來高」,不能改成「已經安全」。重複使用、釣魚、對方網站存明文,都不在這次比對的範圍內。

寫給同事的最短可用句子:命中 = 立刻換掉;未命中 = 只排除了這份名單,下一步仍看是否重複使用、是否隨機產生。

當場核對:看名單檔,再看 Network

口號寫「本機比對、不上傳」無法自證。能當場看到的是兩樣東西:瀏覽器下載了哪份名單,以及你輸入的那串有沒有作為業務資料出站。

先看名單。打開開發者工具的 Network,過濾檔名裡帶 leakedtop 的請求,把回應另存為文字。用編輯器數一下非空行,抽查前幾行是不是 123456password 這類公開高頻密碼。你核過的行數,才是「未命中」這句話的分母。不要憑檔名裡的 10k 直接寫成一萬條。

再看待測密碼。準備一枚不會出現在真實業務裡的金絲雀,例如 canary-audit-2026-x7k,輸入檢測框。勾選 Preserve log,在過濾器裡貼上這串。XHR / Fetch 的請求行、查詢串和請求體都不該出現它;造訪統計的 query 與 body 同樣不該出現。靜態資源、字型和那份名單文字可以出現——名單出站是預期,待測密碼出站才是失敗。

  1. 打開 Network,勾選 Preserve log,先完成一次檢測,再找名單檔的回應並清點行數。
  2. 換一枚金絲雀密碼再測一次,用過濾器搜尋這枚字串;命中任意請求即說明明文離開了分頁。
  3. 沒有命中時,再打開造訪統計請求,確認標題和路徑可以出現,輸入框全文不能出現。

這套步驟證明的範圍很窄:這一次操作裡,待測密碼沒有作為已觀察到的 HTTP 欄位離開目前分頁,名單覆蓋面等於你數過的行數。它不證明擴充功能沒有讀輸入框,也不證明下週更新後的指令碼仍是同一行為。換瀏覽器或換版本後,值得再做一遍金絲雀搜尋。

熵估算和名單是兩件不同的事

檢測頁往往同時給出等級、位元數和「是否命中名單」。把它們當成同一個分數,就會出現「位元數不低、卻命中名單」或「未命中、卻很短」時的困惑。它們回答的問題不同,也不該互相抵消。

熵估算問的是:假如攻擊者按字元集窮舉,平均要試多久。常見寫法是長度乘以 log2(字元集大小),再對重複字元、連續重複做折扣。閾值如果寫成 ≥ 80 bits 為極強、≥ 60 為強、≥ 40 為中,其餘為弱,那只是這條估算函數的分檔,不是實驗室測出的真實破解時間。離線與線上兩條時間線用的猜測速率也不同:例如離線按每秒 1010 次、線上按每秒 103 次,再取平均情況(搜尋空間的一半)。換一套速率,時間會變,密碼本身沒有變。

名單問的是:這串是不是已經被公開濫用。它不使用位元數。一個命中名單的密碼,即使碰巧混進了大寫和符號,仍然該標弱。一個未命中的 6 位密碼,熵會很低,長度本身就會把它壓成弱——這和名單無關。低於 8 位時給出「安全性較低」的提示,依據的是長度,不是外洩庫。

所以一次完整閱讀至少看三處:名單是否命中,長度是否過短,熵落在哪一檔。只有三處都讀過,才談得上「這一串現在看起來像什麼」。它仍然代替不了密碼管理器,也代替不了「每個網站一串隨機密碼」。

用開啟即用的檢測頁把範圍練熟

若你希望用一個把邊界寫清楚的頁面來練習,可以從 MakePwd 的密碼檢測開始。開啟即可使用,無需註冊,也沒有密碼庫。待測密碼按產品說明不上傳,也不會寫入 analytics;比對發生在目前分頁下載的公開高頻名單上,不是 Have I Been Pwned,也不是全網撞庫。命中會強制標為弱;超過 128 位時只做精確比對,不再跑尾部數字和 Leet。

練習時用可丟棄的測試串,不要用現用密碼。同時打開 Network:你應看到名單檔和可能的造訪統計,不應看到輸入框全文。新密碼需要另抽一串時,密碼產生器同樣開啟即用,隨機模式長度 6–128 位,預設 16 位,低於 8 位會提示安全性較低。產生和檢測都在瀏覽器裡完成,明文預設不離開本機。

這些練習的目的不是證明某一個網站「查得最全」,而是讓你能向同事解釋三句話:我核過名單有多少行;我用金絲雀搜過 Network;未命中我只寫成「不在這份名單裡」。換任何聲稱「本機弱密碼檢測」的頁面,步驟可以原樣搬過去。

下次讀檢測結果時記住的三件事

第一,命中就換;未命中只排除了目前這份本機弱密碼名單,不要讀成從未外洩。第二,本機短名單、HIBP 的 5 位雜湊前綴、全量離線庫是三種不同的資料路徑,未命中的含義跟著路徑走。第三,熵和名單不要互相抵消——短密碼可以未命中,長而常見的密碼可以命中。

若你還要繼續追問「明文有沒有作為業務資料離開這個分頁」,請讀線上加密安全嗎?怎麼當場核對明文沒有離開本機。本文只把「弱密碼名單覆蓋什麼」收成可以寫進結論的範圍。