Salt

如何選擇鹽?

  • July 9, 2018

我覺得我錯過了一些關於pickle的資訊。如何選擇鹽?如果您對所有密碼重複使用相同的鹽,是否可以將其計算出來,然後與正常的暴力破解結合使用。產生鹽的常見方法是什麼?

鹽不是秘密。這是加密數據的開放部分。它應該打開以解密數據。

重複使用鹽是不好的。鹽的全部目的是防止彩虹表的使用。如果攻擊者已經解密了一個文本,那麼將它用於其他文本應該並不容易。就好像您對許多文本重複使用相同的鹽一樣,攻擊者創建彩虹表可能是有意義的,因為他可以通過同一個彩虹表解密您的多個文本。

對於您的問題,如何選擇鹽:正如@Swashbuckler 所說,它應該是random。重要提示:不是一次隨機,而是應該為您的每個文本或密碼隨機生成。

TL;DR:使用 /dev/urandom 之類的 16-32 個字節作為鹽。這種類型的鹽最好地防禦某些類型的密碼雜湊威脅。將唯一的鹽與每個密碼雜湊配對很像為每個密碼使用單獨的雜湊函式。

威脅 1:預計算表

密碼破解可以利用預先計算的表。直接的方法是預先生成一個將雜湊映射到密碼的表。當您擁有要破解的密碼雜湊數據庫時,請從與表中條目匹配的雜湊開始。每當新密碼被破解或洩露時,都可以將新密碼/密碼雜湊對添加到列表中。該表可以變得越來越大,而不會顯著增加查找時間。即使您使用強密碼拉伸雜湊函式,不使用鹽意味著只要您有空間儲存新條目,您只需對候選密碼進行一次雜湊處理。

彩虹表是一種不同類型的預計算表,使用的空間更少。他們利用時間-記憶權衡。我將省略細節,因為它們不相關,而且彩虹表很容易被擊敗。

解決方案:使用一種難以預測的鹽。如果你使用一個 $ n $ 位(不可預測的)鹽,然後您將所需“儲存”密碼的數量增加一倍 $ 2^n $ . 這使得這兩種類型的表對於足夠大的表是不可行的 $ n $ . 如果有人已經生成了表,那麼在您的雜湊函式中添加鹽會使這些表無用。如果他們有一個特定鹽的表,那麼它對其他鹽是無用的。

威脅 1½:可預測鹽的表格

如果您的鹽是可預測的(或已知的),那麼準備破解您網站密碼的人可能會在您的密碼數據庫被盜之前生成表格來攻擊您的特定網站或特定使用者的密碼。因此,您應該製作鹽:

  • 一個使用者名。可以為常見的使用者名生成表格。不僅是“John”、“Bob”、“Lucy”,還有“Admin”之類的東西。
  • 一個使用者標識。Web 應用程序開發人員已經考慮使用自動分配的 ID 號作為鹽。兩個問題。1) 帶有使用者 ID 的 URL 或網路流量可能會洩露這些數字。2)當它是數據庫中的自動增量欄位時,可以為低數字生成預生成表。IE。0, 1, 2, 3, … 這些低數量的使用者 ID 對應於具有管理員權限的帳戶的可能性也增加了。
  • 電子郵件地址。這可以讓某人提前為有針對性的攻擊做好準備。
  • 您網站的名稱或域名。為每個密碼使用恆定鹽存在無法預測的問題。

具體解決方案:使用來自同一個 RNG 的 16 字節值來生成新密鑰。

威脅 2:辨識相同的密碼:

沒有鹽,很容易確定兩個帳戶是否具有相同的密碼。如果

$$ x = H(p_1), \ y = H(p_2), \ x = y $$ 然後: $$ p_1 = p_2 $$ 當您添加鹽時,這些條件變為

$$ x = H(s_1, p_1) \ y = H(s_2, p_2) \ x = y \ s_1 = s_2 $$ 如果您為每個密碼輸入使用一種鹽,您將遇到同樣的問題。這種資訊洩漏比看起來要嚴重得多。如果有人可以確定兩個帳戶具有相同的密碼,那麼他們還可以確定哪些帳戶具有弱密碼。將每個密碼雜湊排列在一列中。在另一列中列出密碼雜湊匹配的每個帳戶。按第二列中的帳戶數對錶格進行排序。

您甚至無需測試一個密碼就可以知道第一行中列出的每個人的密碼都有“password1”之類的東西。即使您錯了,然後選擇一個帳戶,在最常見的 1000 個密碼列表中測試每個密碼。找到一個帳戶的密碼後,您就知道可能有數百個特定使用者的密碼。

解決方案:生成隨機鹽。一個 16 字節長的將起作用,並且可能是全球唯一的。從Linux 的 randombytes(bufAddr, 16, 0)Windows 的 cryptgenrandomJava 的 SecureRandom.generateSeed、Python 的os.urandomPHP 的 random_bytes等獲取字節以確保唯一性要比編造一些涉及使用者名、電子郵件地址、域名、硬編碼常量等。

來自理想均勻分佈的隨機數 $ n $ 位編號將是唯一的,並且機率最高可達 $ O(\sqrt{n}) $ 由於生日悖論的樣本。64 位不足以確定您的值是全球唯一的。 $ \sqrt{2^{64}} = 2^{32} \approx 4 \text{ billion} $ . 這對於一個小網站來說是很多,但對於整個網際網路來說卻很小。

每次有人設置密碼時,您都應該生成一個新的鹽。這包括第一次創建帳戶和每次更改密碼時。

威脅 3:一次破解每個帳戶的密碼

向密碼添加鹽不會使破解個人帳戶密碼的速度變慢,但上述攻擊除外。使用鹽足以使密碼破解速度變慢似乎是一種常見的誤解。它不是。

然而,未加鹽(或相同加鹽)的密碼散列和單獨加鹽的散列之間還有另一個關鍵區別。如果每個帳戶都使用相同的鹽,那麼我可以計算一次密碼的雜湊值,然後將其與每個帳戶的密碼雜湊值進行比較以進行匹配。(在進行一次雜湊和一次表查找所需的時間。)如果任何帳戶雜湊匹配,那麼我已經恢復了每個帳戶的密碼。此外,對於雜湊不匹配的每個帳戶,我可以排除每個帳戶密碼的候選密碼。

相反,如果每個帳戶都使用唯一的鹽,那麼我必須分別測試每個帳戶以確定哪些帳戶使用“password123”。這確實會減慢非目標攻擊;我要做 $ numberOfAccounts \times numberOfCandidatePasswords $ 而不僅僅是 $ numberOfCandidatePasswords $ . 但是,如果我只針對一個帳戶,那麼沒有區別,因為 $ numberOfCandidatePasswords = 1 $ .

解決方案:為每個雜湊使用唯一的鹽。

威脅 4:側通道攻擊

密碼散列競賽(導致 Argon2 的競賽)期間,人們擔心 RAM 訪問模式可能會通過記憶體計時啟用側通道攻擊。

有些算法使用密碼相關和密碼無關的數據訪問模式。(Argon2d 和 Argon2i 分別對應依賴和獨立。)兩者都需要使用不可預測的鹽。

Argon2i 需要一種鹽來防止不同類型的預計算。RAM 使用量大的雜湊(如 Argon2、scrypt 和氣球雜湊)需要對 RAM 進行不可預測的訪問。隨機 RAM 查找很難優化超出商品硬體已經做到的程度。如果 RAM 可以較少隨機訪問(通過重新組織記憶體佈局或通過預取),那麼破解者可以獲得優勢。如果可以分析訪問模式以跳過或推遲某些計算,那麼攻擊者可以獲得優勢。進行這些優化需要大量的預處理時間。Argon2 通過使 RAM 訪問模式依賴於鹽來防止這種情況。因此 Argon2i 應該使用不可預測的鹽。

Argon2d 訪問模式依賴於鹽和密碼。(如果不考慮定時攻擊,它會更強大。)如果你的鹽是不可預測的和秘密的,那麼這有助於減輕潛在的定時攻擊。

解決方案:使用不可預測的鹽。盡可能(實際上)盡可能地保密。

結論:

使用至少 16 個字節長的隨機鹽值。使用與生成新密鑰相同的非確定性 CSRNG,以使它們不可預測且唯一。(無需使用超過 32 字節 = 256 位。)每次分配密碼時使用不同的鹽。(在創建帳戶和更改密碼時。)

如果您正在實施新的東西,您應該以這種方式生成鹽。如果您不需要自己實現密碼散列,那麼您不應該這樣做。尋找一個為您工作的現有庫(一個安全且無錯誤的庫)。

例如,如果您使用 PHP,則可以使用password_hash、password_verify 和 password_needs_rehash。這會為您生成鹽,使用 bcrypt 或 Argon2i 的優化本機實現執行密碼拉伸,並為您進行恆定時間雜湊比較。我對此知之甚少,不知道我是否可以完全認可它或它使用的預設配置。

附加資訊:

您不會“加密”或“解密”密碼。儘管字母序列“crypt”出現在“crypt”、“brcrypt”、“md5crypt”、“scrypt”等中,但這是錯誤的術語。加密是可逆的。密碼應該是散列的,這意味著從其散列中獲取密碼的唯一方法應該是將候選密碼的散列與您為實際密碼儲存的散列進行比較。如果正確使用鹽,那麼破解密碼的最快方法應該是從更有可能的候選密碼開始暴力破解。

散列密碼不會自動使其安全。這是垃圾中的垃圾場景。你應該使用強密碼來保護你的東西。您應該使用比線上服務更強的密碼來保護密碼機密。(具有高熵的隨機密碼比“聰明”的解決方案更強大。你會驚訝於有多少人會想到你認為沒有人會想到的東西。)

如果您想通過使散列變慢來使您的密碼更難破解,您可以使用密碼拉伸。(如果有人不使用殭屍網路進行破解,成本會更高。)這個過程稱為密碼拉伸。它使合法密碼檢查和(希望)密碼破解者的散列變慢。

您應該使用針對您的本機硬體優化的任何可用的密碼擴展雜湊函式。在 Javascript、PHP、Python 或 Bash 中實現 Argon2 是個壞主意。它對你來說會很慢,因為它不是最佳的,但關鍵是要讓其他人慢下來,而不是你自己。(出於同樣的原因,使用 sleep 呼叫根本沒有幫助。)如果 bcrypt 可用,最好使用 bcrypt,而不是使用其他東西的緩慢實現。

您不應將 scrypt 用於網站密碼數據庫。它需要比您認為足夠昂貴的更多 RAM。只有增加它的執行時間才能增加它使用的 RAM 量。如果您將其用作密鑰派生函式(Argon2i、scrypt、ballooon hashing),則應該使用使用大量 RAM 的密碼拉伸函式,但更重要的是,您應該使用更高熵的密碼。

術語鹽通常不適用於雜湊算法以外的事物。一些相關的術語是“nonce”、“tweak”和“IV”。還有一個相關的術語“胡椒”可以有多種含義,但通常指的是“像鹽,但秘密”之類的東西。Peppering 不是一個好主意,因為密碼拉伸雜湊算法是更好的選擇。

不要組合兩個密碼拉伸雜湊函式。它永遠不會比使用雙倍成本參數執行一個雜湊更有效。

引用自:https://crypto.stackexchange.com/questions/60259