根據散列和已知的純文字猜測鹽有多難?
我有以下案例:
Alice 擁有該域
alice.com
,Bob 擁有bob.com
. 我希望使用者為自己和特定服務創建一個雜湊,例如facebook.com
ortwitter.com
。該環境是客戶端唯一的應用程序,不涉及伺服器。因此,每個使用者都擁有一個唯一的隨機字元串,該字元串生成一次,本地儲存在使用者的設備上,並打算用作鹽。目標是為每個綁定到服務的使用者提供唯一的雜湊值,而攻擊者無法猜測使用者在特定其他服務上的雜湊值。雜湊旨在成為萬能電子郵件地址的本地部分。Alice's generated email address for facebook.com: tcpcAwdfMGw5S22/98avSvqrO8vyEefLGRpmu5zHWKw@alice.com
使用 argon2 作為散列函式的虛擬碼範例如下所示:
argon2.hash("<service>+<user-domain>", {salt: <user-salt>}) -> hash
Alice、她的域和 facebook 的一個具體範例是:
argon2.hash("facebook.com+alice.com", {salt: <SaltOfAlice>}) -> tcpcAwdfMGw5S22/98avSvqrO8vyEefLGRpmu5zHWKw
請注意,沒有要散列的實際密碼,只是一個由服務域和使用者域組成的字元串。Argon2 被異化以基於此字元串生成雜湊,其中鹽是實際的秘密部分。
這給我們留下了一張使用者、服務、個人域和雜湊表。
User Domain Service Hashed Mail ----------------------------------------------------------------------------------- Alice alice.com facebook.com tcpcAwdfMGw5S22/98avSvqrO8vyEefLGRpmu5zHWKw@alice.com Alice alice.com twitter.com yQYCTrtMbQCq1ufLGCJAsc+Y1SIIYR7rC7Cbgp6e2IA@alice.com Bob bob.com facebook.com B+sKf7kXTH13tfj8ueZdmnTIpWRYCUYeNyQzFFx0jWs@bob.com Bob bob.com twitter.com /EIqXNIG/orOcQfYz/j1IYWTIRvTAoXJ4Di8cESsXwg@bob.com
這些雜湊值將可公開訪問。因此,當攻擊者獲得 Alice 和相關服務(facebook.com、twitter.com 等)和她自己的域(alice.com)的雜湊列表時,攻擊者是否能夠提取鹽?
攻擊者應該無法猜測 Alice 的雜湊電子郵件地址以獲取新服務(例如 stackexchange.com)。
即使每個使用者總是使用相同的鹽並且鹽是保密的,這是否也能保證?
您似乎正在尋找一種從使用者特定秘密創建不同“密碼”的好方法。為此,您不需要密碼雜湊,您可以使用基於公共密鑰的KDF,假設您的密鑰具有對稱密鑰的屬性。
在這種情況下,秘密應該代替密鑰或密碼,而不是雜湊。然後,有關服務和域的資訊應該是“其他資訊”的一部分,或者,如果您對使用密碼散列有一定的限制,那就是 salt。如果對手太容易猜出秘密,則需要密碼雜湊,但請注意,它只能為您提供少量、恆定大小的保護,防止離線猜測攻擊。
為此,您可能應該在字節編碼值前面加上以字節為單位的大小,以確保兩個值一起只有一種可能的編碼。如果它們更大,首先使用安全雜湊 (SHA-256) 對服務和域進行雜湊處理可能是有意義的,因為算法可能不是為大型資訊欄位或鹽設計的 - CPU 可能依賴於編碼尺寸。
所以你會得到類似的東西:
$$ \text{info} = \text{Encode}(\text{service}, \text{domain}) $$ $$ \text{passwordBits} = \text{KDF}(\text{secret}, \text{info}, \text{passwordSizeInBits}) $$ $$ \text{password} = \text{Format}(\text{passwordFormatting}, \text{passwordBits}) $$
或者,如果您考慮資訊的散列:
$$ \text{info} = \text{Hash}(\text{Encode}(\text{service}, \text{domain})) $$
通常可以在 KDF 中包含隨機鹽。這使得創建稍微更安全的結果成為可能,但顯然會犧牲函式的複雜性和表中的額外儲存空間。
我也會儲存 $ \text{passwordFormatting} $ 當然,在你的表中的字元串。即使在 2019 年,不同的服務也會接受不同格式的密碼字元串。您可以從開源密碼管理器中模仿/複製密碼格式,其中密碼是從隨機值生成的。當然首先檢查許可證。
一個不需要格式化方案的非常簡單的格式化方案是 base64url。如果您不設置密碼(因此密碼的大小以位為單位)太大,許多網站都會允許這樣做。
密碼大小當然取決於密碼格式化所需的位數。它可能太大,例如 128 位,然後您可以丟棄在格式化/基本轉換/創建密碼期間不需要的位。
好的基於密鑰的 KDF (KBKDF) 是 HKDF,但如果您沒有可用的 KDF,您也可以使用ANS X9.63 KDF作為 KDF——這可能是最容易實現的。
下面是關於如何使用密碼雜湊的更通用的解釋:
目標是在每個服務上為每個使用者提供唯一的雜湊值,而攻擊者無法猜測使用者在特定其他服務上的雜湊值。
不,主要目標是對密碼保密(當然,在正確的案例中使用它時要對其進行驗證)。相同的雜湊洩漏資訊甚至密碼是鹽的原因。換句話說,雜湊是唯一的是達到目的的一種手段。
這給我們留下了一張使用者、服務、個人域和雜湊表。
通常這些表還包括鹽,例如通過將其包含在密碼雜湊中。鹽不是保密的;這將要求您為每個使用者保留一個秘密值。如果可以的話,那麼您可能一開始就不需要密碼雜湊;您可以將密碼與安全儲存中的密碼進行比較。
我當然也會儲存諸如版本指示器之類的東西,它表示正在使用的迭代次數、密碼派生函式等,因此您可以在需要時(一個一個地)升級條目。
攻擊者應該無法猜測 Alice 的新服務(例如 stackexchange.com)的雜湊值。
這部分不適用於上述問題
您無法使用服務上的雜湊登錄;您需要密碼,該密碼由服務轉換為密碼雜湊。如果您輸入密碼散列,它將計算密碼散列上的密碼散列並且登錄應該失敗(除非實施者犯了巨大的實施錯誤)。同樣,保護雜湊不是目標。密碼需要保護。
即使每個使用者總是使用相同的鹽並且鹽是保密的,這是否也能保證?
嗯,是的,如果密碼散列的輸入參數中有一個秘密部分,並且如果這個秘密是被散列的部分之一,並且如果該秘密具有足夠的熵,那麼計算密碼散列將變得不可能。
但是,如上所述,將鹽保密並沒有多大意義。
有時執行的是提供一個秘密,該秘密是鹽的一部分。然後該部分由秘密部分和一個(通常是隨機生成的)隨機數(可以單獨用作鹽)組成。這被稱為辣椒。
如果沒有這個秘密值,對手就無法開始離線攻擊,因為沒有胡椒就不可能檢查密碼猜測是否正確。然而,這個辣椒對於所有(或可能是大組)密碼都是相同的。它本身不是鹽。
對於這個特定問題,我會使用答案開頭寫下的方案,而不是使用帶胡椒的密碼雜湊
我不認為鹽是你要找的東西,也可能不是 argon2。儘管如果這是您的問題,它可能會起作用。Argon2 是密鑰派生函式,而不是通用雜湊。它適用於散列密碼。如果您想從較差的熵源生成密鑰,argon2 是一個很好的選擇。Salt用於確保我們不能同時攻擊兩個密碼或使用預先計算的表或辨識相同的密碼等。它們通常作為雜湊的前綴並假定為公共的。
您似乎在要求別的東西,每個使用者都有一個密鑰。並且您希望將此密鑰與服務提供商名稱一起使用,以便每個使用者+服務都獲得一個唯一的字元串,但如果沒有密鑰,您將無法為其他服務創建更多此類,也無法辨識給定字元串屬於哪個服務。目前尚不清楚您是否希望擁有密鑰的使用者能夠反轉該過程,您可能更喜歡加密而不是散列,因此合法使用者進行反轉不需要猜測服務提供商名稱。
但是讓我們堅持散列。使用密鑰和服務提供者做一些簡單的事情,比如 HMAC,應該會提供所需的屬性。如果使用者密碼是密碼而不是一個好的隨機密鑰,您將需要首先使用 KDF,例如 Argon2。但是,如果使用者擁有如此強大的密鑰連接,他可以使用具有許多服務名稱的廉價 HMAC 重複使用它,而無需重複昂貴的 Argon2 **。**如果使用者可以安全地儲存隨機密鑰,則根本不需要使用 Argon2 等。