哪個散列函式對會話 ID 來說足夠好?
背景
我正在建構一個 URL 縮短器,要縮短的 URL 可能包含一個SessionId。
為了使 URL 縮短器不損害 SessionId 的安全性,我必須使用滿足與 SessionId 相同要求的縮短策略。
OWASP 指出:
我想做什麼
- 有一個鍵值儲存,其中值是長(未縮短)的 URL,鍵是縮短的 URL 組件。
- 當使用者導航到縮短的 URL 時,會在鍵值儲存中查找長 URL,並將其返回給使用者,然後使用者被重定向。
因此,密鑰至少需要
128 bits (16 bytes)
很長,並且至少提供64 bits
熵,以免損害 SessionId。如果密鑰是值的雜湊,我可以保證密鑰長度,並且知道熵(基於使用的雜湊算法)。
但是我應該使用哪種雜湊算法?
例如,MD5 摘要長度正好是 128 位。但我不知道它的最小熵是多少。
問題
哪種散列算法產生至少 128 位的摘要,至少有 64 位的熵?
(來自 StackOverflow 的 x-post:https ://stackoverflow.com/q/71224441/6517320 )
對您的雜湊問題的簡短回答是“使用 SHA-256”。這就是幾乎所有安全散列問題的答案,除非答案是“使用 SHA-512”。如果您想要 128 位散列,那麼您可以截斷 SHA-256(取第一個或最後 128 位)。SHA-256 中的所有位都是獨立的,因此您可以提取其中的任何 128 個作為雜湊。
也就是說,IMO 您正在錯誤地考慮這個問題。重點不是專門保護 SessionId。問題是 URL 可能包含敏感資訊,其中 SessionId 只是一個範例(如果它儲存在 URL 中)。如果有人已經知道縮短的 URL,他們可以向您的系統詢問完整的 URL,所以這一切都是為了阻止攻擊者通過猜測找到密鑰。您需要使您的密鑰空間稀疏,也就是說“比實際儲存的密鑰數量大得多”。
您正在維護一個鍵/值數據庫,因此根本不需要使用雜湊。您可以為每個 URL 生成一個隨機密鑰。這比散列更好,因為鍵和值之間絕對沒有聯繫。
鑑於您的設計,攻擊者無法離線搜尋。他們必須聯繫您的伺服器。假設您可以每秒處理 1,000 個請求,並且您將總鍵空間擴展為比計劃的 URL 數量大一萬億倍。如果攻擊者可以消耗所有可用頻寬(我希望您可能會注意到……),那麼攻擊者大約需要 15,000 年(大約搜尋空間的 1/2)才能找到單個 URL。只需對每個 IP 地址進行一點速率限制,就可以使這種攻擊變得非常複雜。
鑑於上述情況,如果您想在系統中儲存十億個 URL,您需要一個鍵空間:
log2(1 billion URLs * 1 trillion multiplier) = 80 bits
在 Base58 中(我喜歡這種問題,因為它對人類友好),大約需要 14 個字元。調整上述速率限制值、要防止的攻擊期限和儲存的 URL 數量,您可以選擇密鑰的長度。
您通常可以在此範圍內計算隨機值,而不必擔心衝突(這對性能有好處)。出於同樣的原因,攻擊者很難發現碰撞,您也不太可能意外發生碰撞。但是,如果您想仔細檢查一下可能性有多大,請查看生日攻擊。“任何值發生衝突的可能性”的計算與“攻擊者需要多長時間才能找到衝突”的計算不同,並且在某些情況下會迫使您使用更長的密鑰。
IMO 不需要雜湊。但是,如果您確實需要一個,請使用 SHA-256,將其截斷為您想要的任意位數。