密碼強度

密碼強度，指一個密碼對抗猜測或是暴力破解的有效程度。一般來說，指一個未授權的訪問者得到正確密碼的平均嘗試次數。密碼的強度和其長度、複雜度及不可預測度有關。強密碼可以降低安全漏洞的整體風險，但並不能降低採取其他安全措施的需要。

使用強密碼可以降低整體安全漏洞風險，但強密碼並不能替代其他有效安全控制措施的必要性。特定強度密碼的有效性在很大程度上取決於認證因素（知識因素、所有權因素、生物特徵因素）的設計與實施。本文將重點探討第一個認證因素。

攻擊者提交猜測密碼的速率是衡量一個系統安全性的重要因素。有的系統在多次嘗試失敗後會暫停登入一段時間，在沒有其他安全缺陷時，這種系統可以用相對簡單的密碼保護。然而，系統以某種形式存儲使用者密碼資訊，一旦這些資訊因系統安全被攻破等原因洩露，使用者密碼就可能面臨風險。

2019 年，英國國家網路安全中心（NCSC）分析了洩露帳戶的公共資料庫，以統計人們常用的單詞、短語和字串。榜單中最流行的密碼是 "123456"，出現次數超過 2300 萬次。排名第二的字串 "123456789" 的破解難度並沒有顯著提升，而前五名中還包括 "qwerty"、"password" 和 "1111111"。

## 創建密碼

密碼可以被自動（使用隨機方式）或人為創建出來，後一種更為常見。暴力破解隨機密碼的強度可以精確計算，而計算人類產生的密碼強度是比較難的。

通常，當人們為電腦系統或網際網路網站創建新帳戶時，系統會要求其選擇密碼（有時會提供建議或設置規則限制）。由於人類在這類任務中往往遵循特定模式，而這些模式通常會被攻擊者利用，因此只能對密碼強度進行粗略估計。此外，密碼猜測程序可廣泛獲取常用密碼列表，其中包括各種人類語言的大量在線詞典、從各類網路商業和社交帳戶洩露的明文及哈希密碼資料庫，以及其他常見密碼。這些列表中的所有條目均被視為弱密碼，其簡單變體也不例外。

當下，雖然有便於使用的隨機密碼生成程序，但這些程序生成的隨機密碼往往讓人難以記住，所以人們還是更傾向於自己設置密碼。不過，這種做法本身就存在安全隱患。因為一個人的生活方式、娛樂喜好以及其他突出的個人特點，通常會對其密碼的選擇產生影響。而且，如今網路社交媒體十分盛行，獲取他人資訊變得輕而易舉。

## 密碼驗證

使用密碼進行身份驗證的系統必須具備某種方式來檢查為獲取訪問權限而輸入的任何密碼。如果有效密碼只是簡單地存儲在系統文件或資料庫中，那麼獲得系統足夠訪問權限的攻擊者將獲取所有使用者密碼，這會讓攻擊者得以訪問被攻擊系統上的所有帳戶，而且使用者若在其他系統使用了相同或相似的密碼，這些系統也可能面臨風險。降低這種風險的一種方法是，不存儲密碼本身，而是僅存儲每個密碼的加密哈希值。像安全哈希演算法（SHA）系列這樣的標準加密哈希演算法極難逆向破解，所以獲取到哈希值的攻擊者無法直接還原出密碼。然而，攻擊者一旦掌握了哈希值，就能在離線狀態下快速測試其猜測的密碼。市面上有很多密碼破解程序，這些程序可以針對竊取到的加密哈希值測試大量的嘗試密碼。

計算技術的進步不斷提升密碼猜測測試速度。例如，2010 年喬治亞理工學院研發出利用通用圖形處理器（GPGPU）大幅加速密碼破解的方法。Elcomsoft 公司於 2007 年 8 月發明了使用普通顯卡實現更快密碼恢復的技術，並迅速在美國申請了相關專利。截至 2011 年，市售產品宣稱使用當時的高端圖形處理器，可在標準台式機上實現每秒測試 11.2 萬個密碼的速度。此類設備能在一天內破解六位單字母密碼。通過將計算任務分配至多台配備類似 GPU 的電腦，破解速度可按設備數量同比提升。目前存在需要較長計算時間的特殊密鑰拉伸哈希演算法，可降低密碼猜測速率。儘管使用密鑰拉伸被視為最佳實踐，但許多通用系統仍未採用這一技術。

另一種可能進行快速猜測的情況是當密碼被用來生成加密密鑰時。在此類場景下，攻擊者可快速驗證猜測的密碼是否能成功解密加密數據。例如，某商業產品宣稱每秒可測試 10.3 萬個 WPA 預共享密鑰（PSK）密碼。

如果密碼系統僅存儲密碼的哈希值，攻擊者可以預計算常見密碼變體及所有短於特定長度的密碼的哈希值，從而在獲取哈希值後實現密碼的快速恢復。利用彩虹表技術可以高效存儲大量預計算的密碼哈希值。若要挫敗此類攻擊，可在存儲哈希值的同時附加一個稱為 "加密鹽值" 的隨機數。鹽值會在計算哈希時與密碼混合，這意味著攻擊者在預計算彩虹表時必須為每個密碼存儲所有可能鹽值對應的哈希結果。如果鹽值的取值範圍足夠大（例如 32 位數字），這種攻擊方式將變得不可行。然而許多常用認證系統並未採用鹽值機制，網際網路上甚至存在針對此類系統的彩虹表庫。

### 熵作為衡量密碼強度的指標

密碼強度由資訊熵（單位為香農，Sh）決定，這一概念源自資訊理論。它可被視為存儲特定類型密碼所需的最小資訊量。相關指標是確定猜出密碼所需猜測次數的以 2 為底的對數值，通常稱為 "熵值位數"。例如，一個具有 42 位熵值的密碼，其強度等同於通過公平拋硬幣隨機生成的 42 位字串。換句話說，破解 42 位熵值的密碼需要進行 2⁴² 次（4,398,046,511,104 次）嘗試才能窮盡所有可能。因此，密碼的熵值每增加 1 位，所需猜測次數就翻倍，使攻擊者的破解難度提升一倍。平均而言，攻擊者需要嘗試半數可能的密碼組合才能找到正確答案。

### 隨機密碼

隨機密碼是由指定長度的符號串構成，這些符號通過隨機選取過程從某個符號集中產生，且每個符號被選中的機率均等。符號可以是字符集（如 ASCII 字符集）中的單個字符、設計成可發音的音節，甚至是單詞列表中的單詞（從而形成密碼短語）。

隨機密碼的強度取決於底層數字生成器的實際熵值；然而這些生成器往往並非真正隨機，而是偽隨機的。許多公開可用的密碼生成程序採用編程庫中的隨機數生成器，這類生成器僅提供有限的熵值。但大多數現代作業系統都配備了適用於密碼生成的加密安全隨機數生成器。此外，還可使用普通骰子生成隨機密碼（詳見隨機密碼生成器 § 增強方法）。隨機密碼程序通常能夠確保生成的密碼符合本地密碼策略，例如通過始終混合生成字母、數字和特殊字符。

對於通過隨機選擇過程生成的密碼（從包含 N 個可能符號的集合中選取長度為 L 的符號串），其可能的密碼數量等於字符集大小的 L 次方（即NL）。增加密碼長度 L 或字符集大小 N 均可增強生成密碼的強度。在假設密碼中每個符號獨立生成的前提下，通過資訊熵衡量的隨機密碼強度，等於可能密碼數量的以 2 為底的對數（即 log₂(NL)）。因此，隨機密碼的資訊熵 H 可由以下公式表示：$H = \log_2 N^L = L\log_2 N = L {\log N \over \log 2}$其中，N 為可能的符號數量，L 為密碼中的符號位數。H 的單位為比特。在最後一個表達式中，對數的底數可以是任意值，但需保持底數一致。

符號集｜符號數量 N｜每個符號的熵值 H

阿拉伯數字（0–9）（例如 PIN 碼）｜10｜bits

十六進位數字（0–9，A–F）（例如 WEP 密鑰）｜16｜4.000 bits

不區分大小寫的拉丁字母（a–z 或者 A–Z）｜26｜bits

不區分大小寫的字母數字組合（a–z 或者 A–Z，0–9）｜36｜bits

區分大小寫的拉丁字母（a–z，A–Z）｜52｜bits

區分大小寫的字母數字組合（a–z，A–Z，0–9）｜62｜bits

除空格外的所有 ASCII 可列印字符｜94｜bits

所有拉丁字母補充-1字符｜94｜bits

所有 ASCII 可列印字符｜95｜bits

所有擴展 ASCII 可列印字符｜218｜bits

二進位（0–255 或 8 位 或 1 字節）｜256｜8 bits

Diceware 單詞列表｜7776｜每個單詞 bits

## 弱密碼

弱密碼是易於猜測的密碼，主要有以下幾種：

- 順序或重複的字符：「12345678」、「111111」、「abcdefg」、「asdf」、「qwer」鍵盤上的相鄰字母。
- 使用數字或符號的僅外觀類似替換，例如使用數字「1」、「0」替換英文字母「i」、「O」，字符「@」替換字母「a」等。
- 登錄名的一部分：密碼為登錄名的一部分或完全和登錄名相同。
- 常用的單詞：如自己和熟人的名字及其縮寫，常用的單詞及其縮寫、寵物的名字等。
- 常用數字：比如自己或熟人的生日、證件編號等，以及這些數字與名字、稱號等字母的簡單組合。

下面是一些常見的弱密碼：

- admin —— 太容易猜出
- 123 —— 同上
- abcde —— 同上
- abc123 —— 同上
- 123456 —— 由於文化因素極其常用
- 1234 —— 同上
- 888888 —— 同上
- 1234567890 —— 同上
- susan —— 常見人名
- DonaldJTrump —— 高知名度人物
- monkey —— 常見動物名且正好六位
- password —— 經常被使用，極易猜出
- p@$$\/\/0rd —— 簡單的字母替換，易被軟體破譯
- rover —— 寵物的常用名稱，也是一個單詞
- 12/3/75 —— 日期
- nbusr123 —— 可能是使用者名稱，如果是這樣的話很容易被猜出
- asdf —— 常用鍵盤的鍵排列
- qwerty —— 常用鍵盤的鍵排列
- aaaaa —— 重複的字母，極易被破解
- administrator ——太容易猜出

以上僅列舉了極少部分弱密碼。

一家美國公司SplashData曾經總結出2011年最弱的25個密碼，部分已列於上方。而像let me in這樣的密碼由於屬於常見詞組，很容易被破譯。據統計，3.8%的密碼是字典裡的單詞，12%的密碼是單詞加一個數字，其中2/3的機會密碼是數字1。

很多用戶不更換預設密碼，而大部分電腦系統的預設密碼可以在網路上找到，極易被破解。如果使用者使用個人資訊（例如學號、朋友的名字、熟人的生日、電話號碼或駕駛執照號碼等）作為密碼，那麼密碼便會很容易被破解，因為如今很多個人資訊都可以在網路上找到。

太短的密碼，雖然容易輸入，但是也很容易被攻破。

## 強密碼

一個強密碼通常長度足夠長，排列隨機，這樣就需要花很多時間才能夠破解。下面是強密碼的一些例子（由於以下實例已經公開，所以已經不具備安全性，只作為說明例子）：

- t3MEIfreryeT45410A ——不是字典的單詞，既有數字也有字母
- w2M1gD1cxJhs5UH4pQh1EgjOU9yWYRkk ——同上
- Convert_100£ to Euros! ——足夠長，並且有擴展符號增加強度
- ot$fet÷×』Fr54⅛9&%u ——含鍵盤上沒有的字符
- 9fad37a6aab5912dfa273521d11e0175fa0e8c95 ——隨機字串
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbccdeertttteferwrwerewrwererewreew ——很長的字串幾乎不可能在短時間之內被破解
- hellomicrosoftwikiwikipediaandadminadmintestactioneditsection ——同上
- RBDeT9hqRfS9gw9bEXmRhBrkkgCs2NMfpzWfQXfN3MPZW25wSsHWEsbexVpYtsWs ——同上
- ru0 ej03m06vm03rm3vu04u3d9 g3fu/32u03h3w.6qul4 ——同上，對於兩者之間使用不同輸入法的人極難以破解
- correcthorsebatterystaple——夠長且無意義的句子或單詞組合

上面列出的強密碼的例子的共同特點是相對較長，使用大小寫字母、數字和符號的組合。密碼越長，使用的符號種類越多，就越難破解。值得注意的是，有些系統不支援例如：「#」、「@」和「!」等等符號作為密碼中的字符，因為這些字元可能在有些鍵盤很難找到。在這種情況下，增加其它的數字或字母可以達到同樣的安全效果。

一個10位長的隨機密碼，比如「BpR#e!ai@$」，雖然強度遠弱於上面列出的密碼，但由於常用鍵一共為95個，因此有$95^{10}$種組合，是不可能在短時間內通過全部列舉來破譯的。

目前的密碼建議為：即使沒有使用大小寫字母或加入其他符號，只要密碼夠長，使用一些無意義但便於記憶的句子或單詞組合也足夠安全。例如上例的「correcthorsebatterystaple」就是由四個英文單詞組成。

### 國家標準技術研究所改正建議

2017年6月，國家標準技術研究所（NIST）發佈新的《800-63》指引第三版，改正已沿用超過十年、受各大政府機構、銀行、業界採用的舊建議，不再強調使用人腦難以記憶的特別符號、數字的無意義組合，而且亦不再建議密碼需每九十日汰換，因為經研究證明此項指引並沒有對系統安全帶來有益的效果。NIST文件的舊版原作者伯爾（Bill Burr）並在《華爾街日報》訪問中公開道歉，稱當時他並無得到可靠的數據作嚴謹研究，只依靠來自八十年代、不合時宜的舊文件作為參考，而他的建議亦沒有考慮到一般人的生活習慣及思考模式。負責撰寫新版指引的NIST顧問格拉西（Paul Grassi）指出，舊的要求不利使用，對抵擋駭客攻擊的作用不大；如果使用者能夠在腦海中構想出一幅其他人無法想像的圖畫，以此作為密碼便是最好的，一句夠長的完整句子，會優於較短的字母、數字及符號混合密碼。華爾街日報引用廣泛流傳的xkcd漫畫，指出只要密碼夠長，拼合幾個看似無意義、但便於該使用者記憶的字詞作為密碼，更能有效抵擋駭客攻擊，暴力破解會需要更久的時間。

## 保護使用者密碼

通常，電腦使用者被建議「不要在任何地方因任何原因寫下密碼」或「不要在不同的帳號使用同一個密碼」。實際上，一個電腦使用者通常有十幾個受密碼保護的帳號，並使用同一個密碼。而那些試圖使用不同密碼的使用者往往由於密碼太多，而記不清哪個帳戶和哪個密碼相對應。2005年的一次安全會議上，來自微軟的一個專家提出：「我認為密碼策略應改為你可以寫下你的密碼。我有68個不同的密碼，如果我不允許將他們寫下來，我將怎麼辦？我不得不使用同樣的密碼」。比較好且實際的建議是在一個低安全性的帳號（如bbs）使用簡單的密碼，在高安全性的程序（例如：網路銀行）使用強密碼。

一旦密碼被寫下來，使用者不能將它放在一些明顯的地方，如通信錄，抽屜等。最糟糕可能也是最常見的情況是密碼被寫在一張便條紙上，放在電腦附近。比較安全的做法是放在保險箱裡。

亦可使用密碼管理器管理密碼。