基於雜湊的訊息認證碼(HMAC)是一種用於計算訊息認證碼的機制,涉及雜湊函數與金鑰的結合。這可以用來驗證訊息的完整性和真實性。
此實作深受 Amazon Web Services (AWS Signature V4) 使用的主要身份驗證方法的啟發,因為它非常容易理解,並且有許多程式庫實現它。要使用這種形式的身份驗證,您需要使用密鑰標識符和密鑰,這兩個密鑰通常在管理介面中產生。
HmacAuthentication提供了一個AuthenticationHandler
,它支援 ASP.NET Core 專案中的 HMAC 驗證。
用法:
appsettings.json
檔案中取得。對於 HMAC 驗證,每個應獲得存取權限的用戶端都需要AppId
和ApiKey
。 var hmacAuthenticatedApps = this . Configuration
. GetSection ( " Authentication " )
. GetSection ( " HmacAuthenticatedApps " )
. Get < HmacAuthenticationClientConfiguration [ ] > ( )
. ToDictionary ( e => e . AppId , e => e . ApiKey ) ;
{
"Authentication" : {
"HmacAuthenticatedApps" : [
{
"AppId" : " <some-app-id> " ,
"ApiKey" : " <some-api-key> "
}
]
}
}
Startup.cs
的ConfigureServices
方法中啟用HMAC身份驗證: services
. AddAuthentication ( o =>
{
o . DefaultScheme = HmacAuthenticationDefaults . AuthenticationScheme ;
} )
. AddHmacAuthentication ( HmacAuthenticationDefaults . AuthenticationScheme , " HMAC Authentication " , o =>
{
o . MaxRequestAgeInSeconds = HmacAuthenticationDefaults . MaxRequestAgeInSeconds ;
o . HmacAuthenticatedApps = hmacAuthenticatedApps ;
} ) ;
Startup.cs
的ConfigureServices
方法中加入MemoryCache
(來自Microsoft.Extensions.Caching.Memory)。 HMAC AuthenticationHandler
使用MemoryCache
來決定重播攻擊。 services . AddMemoryCache ( ) ;
Startup.cs
的Configure
方法中啟用身份驗證: app . UseAuthentication ( ) ;
[ Authorize ( AuthenticationSchemes = HmacAuthenticationDefaults . AuthenticationScheme ) ]
[ Route ( " api/[controller] " ) ]
public class HomeController : Controller
{
// ...
}
HmacAuthenticaion還提供DelegatingHandler
,用於將 HMAC 授權標頭新增至 HTTP 請求。
使用ApiKeyDelegatingHandler
實例化您的HttpClient
實例。確保您不會為每個請求建立新的HttpClient
實例(另請參閱此部落格文章以了解詳細資訊):
new HttpClient ( new ApiKeyDelegatingHandler ( appId , apiKey ) ) ;
或者,如果您的 WebAPI 用戶端是另一個 ASP.NET WebAPI (>= ASP.NET Core 2.1),請在Startup.cs
中註冊您的HttpClient
,如下所示:
services . AddTransient ( sp => new ApiKeyDelegatingHandler ( appId , apiKey ) ) ;
services
. AddHttpClient ( " HmacHttpClient " )
. AddHttpMessageHandler < ApiKeyDelegatingHandler > ( ) ;
要產生 API 金鑰,可以使用以下簡單的控制台應用程式。 .NET Fiddle 上也提供了此實作。
using System . Security . Cryptography ;
public class Program
{
public static void Main ( )
{
Console . WriteLine ( $" AppID: { Guid . NewGuid ( ) } or <some-speaking-name> " ) ;
Console . WriteLine ( $" ApiKey: { GenerateApiKey ( ) } " ) ;
}
private static string GenerateApiKey ( )
{
using ( var cryptoProvider = new RNGCryptoServiceProvider ( ) )
{
byte [ ] secretKeyByteArray = new byte [ 32 ] ; //256 bit
cryptoProvider . GetBytes ( secretKeyByteArray ) ;
return Convert . ToBase64String ( secretKeyByteArray ) ;
}
}
}
安全風險的最大來源通常不是在身分驗證協定中,而是在圍繞其使用的策略和程序中。強烈鼓勵實施者評估該模組如何滿足他們的安全要求。本節包含安全注意事項的不完整列表,在伺服器上部署此 Auth 協定之前必須查看和理解這些注意事項。規範中提供的許多保護措施取決於是否使用以及如何使用。
HmacAuthentication不提供任何機制來取得或傳輸所需的共用憑證集。用於取得HmacAuthentication憑證的任何機制都必須確保使用傳輸層機制(例如 TLS)來保護這些傳輸。
雖然HmacAuthentication提供了一種驗證 HTTP 請求完整性的機制,但它不提供請求機密性的保證。除非採取其他預防措施,否則竊聽者將能夠完全存取請求內容。伺服器應仔細考慮可能作為此類請求的一部分發送的資料類型,並採用傳輸層安全機制來保護敏感資源。
HmacAuthentication提供伺服器真實性的有限驗證。當收到伺服器回傳的回應時。
敵對方可以透過攔截客戶端的請求並返回誤導或其他不正確的回應來利用這一點。服務提供者在使用此協定開發服務時應考慮此類攻擊,並且對於資源伺服器或伺服器回應的真實性存在問題的任何請求,應要求傳輸層安全性。
HmacAuthentication金鑰的功能與傳統驗證系統中的密碼相同。為了計算請求 MAC,伺服器必須能夠存取明文形式的金鑰。例如,這與現代作業系統形成鮮明對比,現代作業系統僅儲存使用者憑證的單向雜湊值。
如果攻擊者獲得對這些金鑰的存取權限,或者更糟的是,獲得所有此類金鑰的伺服器資料庫的存取權限,他或她將能夠代表任何資源擁有者執行任何操作。因此,伺服器保護這些金鑰免遭未經授權的存取至關重要。
除非使用傳輸層安全協議,否則竊聽者將能夠完全存取經過身份驗證的請求和請求 MAC 值,因此能夠發動離線強力攻擊以恢復所使用的金鑰。伺服器應小心分配足夠長且足夠隨機的金鑰,以至少在HmacAuthentication憑證有效的時間內抵禦此類攻擊。
例如,如果憑證的有效期為兩週,伺服器應確保不可能發動在不到兩週內恢復金鑰的暴力攻擊。當然,我們建議伺服器謹慎行事,並合理使用最長的金鑰。
同樣重要的是,用於產生這些金鑰的偽隨機數產生器 (PRNG) 必須具有足夠高的品質。許多 PRNG 實現生成的數字序列可能看起來是隨機的,但它們仍然表現出模式或其他弱點,使密碼分析或暴力攻擊變得更容易。實施者應謹慎使用加密安全的 PRNG 以避免這些問題。
請求 MAC 僅涵蓋 HTTP Host
標頭、 Content-Type
標頭以及可選的一組給定標頭。它不涵蓋它不知道的任何其他標頭,這些標頭通常會影響伺服器解釋請求正文的方式。如果伺服器行為受到此類標頭的存在或值的影響,則攻擊者可以在不被發現的情況下操縱請求標頭。實施者應使用headers
功能透過受請求 MAC 保護的Authorization
標頭來傳遞要新增至簽署的標頭。然後,簽名基字串將負責將這些給定標頭添加到簽名中,以便它們成為 MAC 的一部分。
執行回應身份驗證時,僅涵蓋回應正文(有效負載)和客戶端在其請求中提供的一些請求訊息,例如時間戳記和隨機數。它不包括 HTTP 狀態代碼或任何其他可能影響客戶端行為的回應標頭欄位(例如位置)。
如果攻擊者能夠操縱此資訊並導致客戶端使用不正確的時間,則將能夠導致客戶端將來使用時間產生經過身份驗證的請求。當客戶端發送此類請求時,此類請求將失敗,並且不太可能在伺服器上留下痕跡(考慮到隨機數的常見實現,如果強制執行的話)。然後,攻擊者將能夠在正確的時間重播請求而不被偵測到。
此問題的解決方案是客戶端和伺服器之間的時鐘同步。為了實現這一點,伺服器在收到無效時間戳記時通知客戶端其當前時間。這以回應中的日期標頭的形式發生。請參閱 RFC2616 作為其動機。
客戶端應僅在以下情況下使用伺服器提供的時間資訊:
當收到帶有錯誤時間戳記的請求時,伺服器會向客戶端提供當前時間。客戶端絕不能使用從伺服器接收的時間來調整自己的時鐘,而只能使用它來計算與該特定伺服器通訊的偏移量。
HmacAuthentication根據傳入的 HTTP 主機標頭驗證傳入請求的 MAC。惡意用戶端可以建立指向伺服器 IP 位址的新主機名,並透過傳送針對伺服器所使用的主機名稱以外的另一個主機名稱的有效請求來利用該主機名稱進行攻擊。伺服器實現者必須手動驗證收到的主機標頭是否符合他們的期望。例如,如果您期望在 test.myapi.com 上進行 API 呼叫,請驗證該網域是否是伺服器實作中請求傳送到的網域。