我應該使用 HMAC 創建多部分 HASH 令牌嗎
我有一個帶有自定義 API 身份驗證系統的 Web API,每個使用者都有一個SecretKey和一個公共ApiKey。使用這兩個密鑰客戶端(或使用者)可以為伺服器上的身份驗證生成令牌。
考慮這個函式生成一個身份驗證令牌
public string GetToken(string apiKey, string secretKey, string expireTimestamp) { using var hashAlgorithm = SHA256.Create(); var byteValue = Encoding.UTF8.GetBytes(apiKey + secretKey + expireTimestamp) var byteHash = hashAlgorithm.ComputeHash(byteValue) return Convert.ToBase64String(byteHash) + expireTimestamp }
所以一個令牌是一個組合
$$ token = SHA256(APIKey \mathbin| SecretKey \mathbin| expireTimestamp) \mathbin| expireTimestamp $$
使用這個令牌,我們的 API 有一個獨特的可過期認證系統,
問題:
- 我應該連接鍵+ expTime還是應該使用HMAC之類的東西?這種情況是否容易受到沒有 HMAC的長度擴展攻擊等攻擊?
- 這個系統的漏洞是什麼(如果有的話)?
使用$$ token = SHA256(APIKey \mathbin| SecretKey \mathbin| expireTimestamp) \mathbin| expireTimestamp $$
不安全,因為它可能導致長度擴展攻擊;
$$ token2 = SHA256(APIKey \mathbin| SecretKey \mathbin| expireTimestamp | \color{red}{extension}) \mathbin| (expireTimestamp | \color{red}{extension}) $$
這是偽造的有效令牌。
NIST 要求 SHA3 候選者能夠抵抗長度擴展攻擊。Keccak 現在將 SHA3 命名為獲勝者,而 Blake2 仍然是競爭中的一個不錯的選擇。兩者都可以抵抗長度擴展攻擊,Keccak 使用容量和 Blake2 使用HAIFA構造,都是安全的長度擴展攻擊。
減輕一個可以使用 HMAC;
$$ token = \operatorname{HMAC-SHA256}(privateKey, publicKey \mathbin| expireTimestamp) \mathbin| expireTimestamp $$請注意,這將呼叫 SHA-256 至少兩次(如果密鑰長於散列函式的塊大小,則為 3 次,SHA-256 為 512 位)。
我們可以使用 BLAKE2 來代替 HMAC。BLAKE2 非常快,甚至我們有一個並行版本BLAKE3並使用
$$ token = \operatorname{BLAKE2}( publicKey \mathbin| privateKey \mathbin|expireTimestamp) \mathbin| expireTimestamp $$是安全的。
NIST 還為 SHA3 標準化了一個 MAC,名為KMAC(或此處)。
BLAKE2 和 KMAC 都優於 HMAC。
如果您堅持使用具有 256 位輸出大小的 SHA2,則使用 SHA-512/256,它是 SHA-512/256 的截斷版本,具有不同的初始值來分隔域。SHA-512/256 不受長度擴展攻擊,並且在設計上對 64 位 CPU 友好。