共用方式為


設定 ASP.NET Core 資料保護

當資料保護系統初始化時,其會根據操作環境套用預設設定。 這些設定適用於在單一機器上執行的應用程式。 不過,在某些情況下,開發人員可能會想要變更預設設定:

  • 應用程式會分散到多部機器。
  • 基於合規性考慮。

在這些案例中,資料保護系統提供豐富的組態 API。

Warning

與組態檔類似,資料保護金鑰通道應使用適當的權限加以保護。 您可以選擇待用加密密鑰,但這不會防止網路攻擊者建立新的密鑰。 因此,您的應用程式的安全性會受到影響。 使用資料保護所設定的儲存位置應受限於應用程式本身的存取,類似於您保護組態檔的方式。 例如,如果您選擇將鑰匙圈儲存在磁碟上,請使用檔案系統權限。 請確定只有 Web 應用程式執行所在的身分識別具有該目錄的讀取、寫入和建立存取權。 如果您使用 Azure Blob 儲存體,則只有 Web 應用程式才能夠在 Azure Blob 儲存體讀取、寫入或建立新項目等。

擴充方法 AddDataProtection 會傳回 IDataProtectionBuilderIDataProtectionBuilder 公開了擴充方法,您可以將其鏈結在一起以設定資料保護選項。

Note

本文是針對在 Docker 容器內執行的應用程式所撰寫。 在 Docker 容器中,應用程式一律具有相同的路徑,因此,相同的應用程式分辨器。 需要在多個環境中執行的應用程式 (例如本機和已部署),必須設定環境的預設應用程式分辨器。 在多個環境中執行應用程式已超出本文的範圍。

本文中使用的資料保護延伸模組需要下列 NuGet 封裝:

使用 Azure Key Vault 保護金鑰 (ProtectKeysWithAzureKeyVault

若要使用開發人員認證在 本機與 Azure Key Vault 互動,請在 Visual Studio 中登入您的記憶體帳戶,或使用 Azure CLI 登入。 如果您尚未安裝 Azure CLI,請參閱 如何安裝 Azure CLI。 當您不使用 Visual Studio 時,您可以在 Visual Studio 的開發人員 PowerShell 面板或命令殼層中執行下列命令:

az login

如需詳細資訊,請參閱 使用開發人員工具登入 Azure

在 Entra 或 Azure 入口網站中建立金鑰保存庫時:

  • 將金鑰保存庫設定為使用 Azure 角色型存取控制 (RABC)。 如果您未在 Azure 虛擬網路上運行,包括用於本機開發和測試,請確認在 網路步驟中公用存取已啟用。 啟用公用存取只會公開金鑰保存庫端點。 存取仍然需要已驗證的帳戶。

  • 建立 Azure 受控 Identity 角色(或將角色新增至您打算使用的現有受控 Identity 角色),並搭配 Key Vault 密碼編譯使用者 角色。 將受控Identity指派給裝載部署的 Azure App Service:設定>Identity>使用者指派>新增

    Note

    如果您也計畫在本機使用授權的使用者以取得 Blob 存取來執行應用程式,且使用 Azure CLI 或 Visual Studio 的 Azure 服務驗證,請在 訪問控制 (IAM) 中,新增您的開發人員 Azure 用戶帳戶,並賦予 Key Vault 密碼編譯使用者 角色。 如果您想要透過Visual Studio使用 Azure CLI,請從開發人員 PowerShell 面板執行 az login 命令,並遵循提示向租用戶進行驗證。

  • 當金鑰加密作用中時,金鑰檔案中的金鑰會包含批注「This key is encrypted with Azure Key Vault.」。啟動應用程式之後,請從金鑰列結尾的內容選單中選取檢視/編輯命令,以確認金鑰存在並已套用金鑰保存庫的安全性。

  • 您可以選擇性地啟用自動金鑰庫金鑰輪替,而不必擔心需要使用基於過期或輪替的金鑰庫金鑰來解密承載的資料。 每個產生的數據保護金鑰都包含用來加密金鑰保存庫金鑰的參考。 只要確定您保留過期的金鑰保存庫金鑰,請勿將其刪除在密鑰保存庫中。 此外,請在應用程式的金鑰保存庫組態中使用無版本金鑰標識碼,其中標識元結尾不會放置任何密鑰 GUID(例如: https://contoso.vault.azure.net/keys/data-protection)。 針對兩個金鑰使用類似的輪替期間,金鑰保存庫金鑰會比數據保護密鑰更頻繁地輪替,以確保在數據保護密鑰輪替時使用新的金鑰保存庫金鑰。

使用 Azure Key Vault 保護金鑰,實作了IXmlEncryptor,它會停用自動資料保護設定,包括停用金鑰環的儲存位置。 若要將 Azure Blob 記憶體提供者設定為將金鑰儲存在 Blob 記憶體中,請遵循 ASP.NET Core 中密鑰記憶體提供者中的 指引,並在應用程式中呼叫其中 PersistKeysToAzureBlobStorage 一個多載。 下列範例會使用接受 Blob URI 和令牌認證的多載TokenCredential,依賴 Azure 受控Identity 進行角色為基礎的存取控制(RBAC)。

若要設定 Azure Key Vault 提供者,請呼叫其中一個 ProtectKeysWithAzureKeyVault 的多載函式。 下列範例會使用接受密鑰標識碼和令牌憑證的多載,TokenCredential 依賴於生產環境中的 Managed Identity 以 RBAC 進行操作,或在開發和測試期間使用 ManagedIdentityCredential。 其他重載可接受金鑰保存庫客戶端或具有客戶端密碼的應用程式客戶端識別碼。 如需詳細資訊,請參閱 ASP.NET Core 中的金鑰儲存提供者

如需 Azure SDK API 和驗證的詳細資訊,請參閱 使用 Azure 連結庫向 Azure Identity 服務驗證 .NET 應用程式 ,並使用 Azure 角色型存取控制提供 Key Vault 金鑰、憑證和秘密的存取權。 如需記錄指引,請參閱 使用適用於 .NET 的 Azure SDK 進行記錄:不使用客戶端註冊進行記錄。 對於使用相依性注入的應用程式,應用程式可以呼叫 AddAzureClientsCore,並將 true 作為 enableLogForwarding 傳遞,以建立和配置日誌基礎架構。

若要在 Azure 入口網站中建立金鑰,請參閱 快速入門:使用 Azure 入口網站從 Azure 金鑰保存庫設定和擷取金鑰。 至少給金鑰 GetUnwrap KeyWrap Key 權限。 記錄金鑰識別碼以用於應用程式的設定。 如果您打算啟用金鑰保存庫金鑰的自動輪替,請記錄 無版本 金鑰識別碼,其中不會將金鑰 GUID 放在識別碼結尾 (例如: https://contoso.vault.azure.net/keys/data-protection)。

在註冊服務的檔案Program中:

TokenCredential? credential;

if (builder.Environment.IsProduction())
{
    credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
    // Local development and testing only
    DefaultAzureCredentialOptions options = new()
    {
        // Specify the tenant ID to use the dev credentials when running the app locally
        // in Visual Studio.
        VisualStudioTenantId = "{TENANT ID}",
        SharedTokenCacheTenantId = "{TENANT ID}"
    };

    credential = new DefaultAzureCredential(options);
}

builder.Services.AddDataProtection()
    .SetApplicationName("{APPLICATION NAME}")
    .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
    .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);

{MANAGED IDENTITY CLIENT ID}:Azure 託管的 Identity 客戶端識別碼 (GUID)。

{TENANT ID}:租使用者標識碼。

{APPLICATION NAME}SetApplicationName 設定資料保護系統中此應用程式的唯一名稱。 應用程式部署間的值應保持一致。

{BLOB URI}:金鑰檔案的完整 URI。 當您建立密鑰檔案時,Azure 記憶體會產生 URI。 請勿使用 SAS。

{KEY IDENTIFIER}:用於密鑰加密的 Azure Key Vault 金鑰標識碼。 存取原則可讓應用程式使用 GetUnwrap KeyWrap Key 許可權存取金鑰保存庫。 建立金鑰後,可以從 Entra 或 Azure 入口網站中的金鑰取得金鑰版本。 如果您啟用金鑰保存庫金鑰的自動輪替,請確定您在應用程式的金鑰保存庫設定中使用 無版本 金鑰識別碼,其中不會將金鑰 GUID 放在識別碼結尾 (範例: https://contoso.vault.azure.net/keys/data-protection)。

若要讓應用程式與 Azure Key Vault 進行通訊和授權, Azure.Identity 應用程式必須參考 NuGet 套件

Note

如需將套件新增至 .NET 應用程式的指引,請參閱 套件取用工作流程 (NuGet 文件) 下的安裝和管理套件相關文章。 在 NuGet.org確認正確的套件版本。

Note

在非生產環境中,上述範例會使用 DefaultAzureCredential 來簡化驗證,同時開發部署至 Azure 的應用程式,方法是將 Azure 主控環境中所使用的認證與本機開發中使用的認證結合在一起。 如需詳細資訊,請參閱 使用系統指派的受控識別向 Azure 資源驗證 Azure 裝載的 .NET 應用程式

如果應用程式使用舊版 Azure 套件 (Microsoft.AspNetCore.DataProtection.AzureStorageMicrosoft.AspNetCore.DataProtection.AzureKeyVault),建議您 移除 這些參考並升級至 Azure.Extensions.AspNetCore.DataProtection.BlobsAzure.Extensions.AspNetCore.DataProtection.Keys 套件。 較新的套件可解決重要的安全性和穩定性問題。

替代的共用存取簽章(SAS)方法:作為透過受控 Identity 存取 Azure Blob 儲存體中密鑰 Blob 的替代方法,您可以呼叫 PersistKeysToAzureBlobStorage,它可接受包含 SAS 令牌的 Blob URI 的多載。 下列範例將繼續使用 ManagedIdentityCredential (production,生產環境)或 DefaultAzureCredential (development,開發及測試環境)作為其 TokenCredential,如前述範例所示。

builder.Services.AddDataProtection()
    .SetApplicationName("{APPLICATION NAME}")
    .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
    .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);

{APPLICATION NAME}SetApplicationName 設定資料保護系統中此應用程式的唯一名稱。 應用程式部署間的值應保持一致。

{BLOB URI WITH SAS}:金鑰檔案應存放的完整 URI,其中包含作為查詢字串參數的 SAS 令牌。 當您要求為上傳的密鑰檔案生成 SAS 時,Azure 儲存會產生 URI。

{KEY IDENTIFIER}:用於密鑰加密的 Azure Key Vault 金鑰標識碼。 存取原則可讓應用程式使用 GetUnwrap KeyWrap Key 許可權存取金鑰保存庫。 建立金鑰後,可以從 Entra 或 Azure 入口網站中的金鑰取得金鑰版本。 如果您啟用金鑰保存庫金鑰的自動輪替,請確定您在應用程式的密鑰保存庫組態中使用無版本金鑰標識碼,其中沒有將密鑰 GUID 放在標識子結尾(例如: https://contoso.vault.azure.net/keys/data-protection)。

將金鑰儲存到檔案系統 (PersistKeysToFileSystem

若要將金鑰儲存在 UNC 共用上,而不是儲存在 %LOCALAPPDATA% 的預設位置,請使用 PersistKeysToFileSystem 設定系統:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));

Warning

如果您變更金鑰持續性位置,系統就不會再自動加密待用密鑰,因為它不知道 DPAPI 是否為適當的加密機制。

在資料庫中儲存金鑰 (PersistKeysToDbContext

若要使用 EntityFramework 將金鑰儲存在資料庫中,請使用 Microsoft.AspNetCore.DataProtection.EntityFrameworkCore 封裝來設定系統:

builder.Services.AddDataProtection()
    .PersistKeysToDbContext<SampleDbContext>();

上述程式碼會將金鑰儲存在設定的資料庫中。 所使用的資料庫內容必須實作 IDataProtectionKeyContextIDataProtectionKeyContext 會公開屬性 DataProtectionKeys

public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = null!;

這個屬性代表儲存索引鍵的資料表。 手動建立資料表,或使用 DbContext 遷移功能建立資料表。 如需詳細資訊,請參閱DataProtectionKey

保護金鑰設定 API (ProtectKeysWith\*

您可以透過呼叫任何 ProtectKeysWith\* 設定 API 來配置系統以保護靜態的金鑰。 請考慮下列範例,它會將密鑰儲存在 UNC 共用上,並使用特定的 X.509 憑證加密待用密鑰。

您可以從檔案中提供 X509Certificate2ProtectKeysWithCertificate,並呼叫 X509CertificateLoader.LoadCertificateFromFile

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(
        new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));

下列程式代碼範例示範如何使用指紋載入憑證:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);

您可以提供 X509Certificate2ProtectKeysWithCertificate,例如從檔案載入的憑證:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(
        new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));

下列程式代碼範例示範如何使用指紋載入憑證:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);

如需內建密鑰加密機制的範例和討論,請參閱 使用 ASP.NET Core 在 Windows 和 Azure 中待用密鑰加密

使用任何憑證解除保護金鑰 (UnprotectKeysWithAnyCertificate

您可以使用由X509Certificate2UnprotectKeysWithAnyCertificate組成的憑證陣列來輪替憑證及解密待用密鑰。

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(
        new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]))
    .UnprotectKeysWithAnyCertificate(
        new X509Certificate2("certificate_1.pfx", builder.Configuration["CertificatePassword_1"]),
        new X509Certificate2("certificate_2.pfx", builder.Configuration["CertificatePassword_2"]));

設定預設金鑰存留期 (SetDefaultKeyLifetime

若要將系統設定為使用 14 天而不是預設 90 天的金鑰存留期,請使用 SetDefaultKeyLifetime

builder.Services.AddDataProtection()
    .SetDefaultKeyLifetime(TimeSpan.FromDays(14));

設定應用程式名稱 (SetApplicationName

根據預設,資料保護系統會根據應用程式的內容根目錄路徑相互隔離,即使它們共用相同的實體金鑰存放庫也是如此。 此隔離可防止應用程式理解彼此的受保護承載。

若要在應用程式之間共用受保護的承載:

builder.Services.AddDataProtection()
    .SetApplicationName("<sharedApplicationName>");

SetApplicationName 在內部設定了 DataProtectionOptions.ApplicationDiscriminator。 基於疑難排解目的,可以使用在 WebApplication 中構建 Program.cs 之後置的下列程式碼來紀錄架構指派至鑑別子的值:

var discriminator = app.Services.GetRequiredService<IOptions<DataProtectionOptions>>()
    .Value.ApplicationDiscriminator;
app.Logger.LogInformation("ApplicationDiscriminator: {ApplicationDiscriminator}", discriminator);

如需如何使用鑑別子的詳細資訊,請參閱本文後續的章節:

Warning

在 .NET 6 中,WebApplicationBuilder 會將內容根路徑正規化,使其以 DirectorySeparatorChar 結尾。 例如,在 Windows 上,內容根路徑會以 \ 結尾,而在 Linux 以 / 結尾。 其他主機不會正規化路徑。 大部分從 HostBuilderWebHostBuilder 移轉的應用程式都不會共用相同的應用程式名稱,因為其不會以 DirectorySeparatorChar 終止。 若要解決此問題,請移除目錄分隔符號字元,並手動設定應用程式名稱,如下列程式碼所示:

using System.Reflection;
using Microsoft.AspNetCore.DataProtection;

var builder = WebApplication.CreateBuilder(args);

var trimmedContentRootPath = 
    builder.Environment.ContentRootPath.TrimEnd(Path.DirectorySeparatorChar);

builder.Services.AddDataProtection().SetApplicationName(trimmedContentRootPath);

var app = builder.Build();

app.MapGet("/", () => Assembly.GetEntryAssembly()!.GetName().Name);

app.Run();

停用自動產生金鑰 (DisableAutomaticKeyGeneration

您可能會遇到這樣的案例:不希望應用程式自動滾動金鑰(建立新金鑰),因為金鑰即將到期。 這種情況的一個例子可能是以主次關係設定的應用程式,其中只有主應用程式負責密鑰管理,而次要應用程式僅具有密鑰環的唯讀檢視。 藉由 DisableAutomaticKeyGeneration 設定系統,可以將次要應用程式設定為將金鑰環視為唯讀:

builder.Services.AddDataProtection()
    .DisableAutomaticKeyGeneration();

每個應用程式的隔離

當資料保護系統由 ASP.NET Core 主機提供時,其會自動將應用程式相互隔離,即使這些應用程式是在相同的背景工作處理序帳戶下執行,且使用相同的主要金鑰資料也一樣。 這類似於 System.Web 的 <machineKey> 元素中之 IsolateApps 修飾元。

隔離機制的運作方式是將本機電腦上的每個應用程式視為唯一租用戶,因此任何指定應用程式的根目錄 IDataProtector 會自動將應用程式識別碼納入為鑑別子 (ApplicationDiscriminator)。 應用程式的唯一識別碼是應用程式的實體路徑:

  • 針對裝載於 IIS 的應用程式,唯一識別碼是應用程式的 IIS 實體路徑。 如果應用程式部署在 Web 服務器陣列環境中,則此值是穩定的 (假設 IIS 環境在 Web 服務器陣列中的所有機器上都以相似的方式進行設定)。
  • 對於在 Kestrel 伺服器上執行的自我裝載應用程式,唯一識別碼是磁碟上應用程式的實體路徑。

唯一識別碼的設計目的是要能夠在重設之後繼續存在,無論是應用程式本身重設還是整個機器重設。

此隔離機制假設應用程式不具惡意。 惡意應用程式可能會影響在相同工作流程帳戶下執行的任何其他應用程式。 在應用程式互不受信任的共用裝載環境中,裝載提供者應採取步驟確保應用程式之間的作業系統層級隔離,包括分隔應用程式的基礎金鑰存放庫。

如果 ASP.NET Core 主機未提供資料保護系統 (例如,如果您透過 DataProtectionProvider 具體類型具現化該保護系統),則根據預設,系統會停用應用程式隔離。 停用應用程式隔離時,只要應用程式提供適當的目的,則相同金鑰資料支援的所有應用程式都可以共用承載。 若要在此環境中提供應用程式隔離,請在組態物件上呼叫 SetApplicationName 方法,並為每個應用程式提供唯一的名稱。

資料保護和應用程式隔離

針對應用程式隔離,請考慮下列幾點:

  • 當多個應用程式指向相同的金鑰存放庫時,目的是讓這些應用程式共用相同的主要金鑰資料。 資料保護的開發假設是,所有共用金鑰通道的應用程式都可以存取該金鑰通道中的所有項目。 應用程式唯一識別碼可用來隔離衍生自金鑰通道所提供金鑰的應用程式特定金鑰。 不期望使用項目層級的權限,例如 Azure KeyVault 所提供的,用於強制實施額外的隔離。 嘗試項目層級權限會產生應用程式錯誤。 如果您不想依賴內建應用程式隔離,則應該使用個別的金鑰存放區位置,而不使在應用程式之間共用。

  • 應用程式鑑別子 (ApplicationDiscriminator) 用於允許不同的應用程式共用相同的主要金鑰資料,並以維持其加密載荷彼此區別。 若要讓應用程式能夠讀取彼此的密碼編譯承載,其必須具有相同的應用程式鑑別子,這可以藉由呼叫 SetApplicationName 進行設定。

  • 如果應用程式遭到入侵(例如,透過 RCE 攻擊),則該應用程式可存取的所有主要密鑰數據也必須被視為遭到入侵,而不論其待用保護狀態為何。 這表示,如果兩個應用程式指向相同的存放庫,即使它們使用不同的應用程式鑑別子,只要一個應用程式遭到入侵,在功能上皆等同於兩者遭到入侵。

    即使這兩個應用程式使用不同的機制來保護靜態密鑰,這個「功能上相當於兩者妥協的」條款仍然適用。 一般而言,這不是預期的設定。 待用保護機制的目的是在網路攻擊者取得存放庫的讀取存取權時提供保護。 取得存放庫寫入權限的網路攻擊者 (可能是因為其在應用程式內取得程式碼執行權限) 可向儲存體中插入惡意金鑰。 資料保護系統故意不提供保護,以防止網路攻擊者取得對金鑰存放庫的寫入存取。

  • 如果應用程式之間需要保持真正的隔離,則應使用不同的金鑰存放庫。 這自然脫離了「隔離」的定義。 如果應用程式具有彼此資料存放區的讀取和寫入存取,則不會進行隔離。

更改演算法 UseCryptographicAlgorithms

資料保護堆疊可讓您變更新產生金鑰所使用的預設演算法。 若要這樣做,最簡單的方法是從組態回撥呼叫 UseCryptographicAlgorithms

builder.Services.AddDataProtection()
    .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration
    {
        EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
        ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
    });

預設 EncryptionAlgorithm 為 AES-256-CBC,而預設 ValidationAlgorithm 為 HMACSHA256。 預設原則可由系統管理員透過全機器原則設定,但針對 UseCryptographicAlgorithms 的明確呼叫會覆寫預設原則。

呼叫 UseCryptographicAlgorithms 可讓您從預先定義的內建清單中指定所需的演算法。 您不需要擔心演算法的實作。 在上述案例中,若是 Windows 上執行,則資料保護系統會嘗試使用 AES 的 CNG 實作。 否則,其會回復為受控 System.Security.Cryptography.Aes 類別。

您可以透過呼叫 UseCustomCryptographicAlgorithms 來手動指定實作。

Tip

變更演算法不會影響金鑰通道中的現有金鑰。 其只會影響新產生的金鑰。

指定自訂受控演算法

若要指定自訂受控演算法,請建立指向實作類型的 ManagedAuthenticatedEncryptorConfiguration 執行個體:

builder.Services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new ManagedAuthenticatedEncryptorConfiguration
    {
        // A type that subclasses SymmetricAlgorithm
        EncryptionAlgorithmType = typeof(Aes),

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // A type that subclasses KeyedHashAlgorithm
        ValidationAlgorithmType = typeof(HMACSHA256)
    });

一般而言,*Type 屬性必須指向 SymmetricAlgorithmKeyedHashAlgorithm 的具體、可具現化 (透過公用無參數的建構函式) 實作,不過為了方便起見,系統針對某些值 (例如,typeof(Aes)) 進行了特殊處理。

Note

SymmetricAlgorithm 的金鑰長度必須 ≥ 128 位元,區塊大小 ≥ 64 位元,且必須支援使用 PKCS #7 填補的 CBC 模式加密。 KeyedHashAlgorithm 的雜湊大小必須為 >= 128 位元,且必須支援長度等於雜湊演算法雜湊長度的金鑰。 KeyedHashAlgorithm 並非必須為 HMAC。

指定自訂 Windows CNG 演算法

若要使用 CBC 模式加密搭配 HMAC 驗證來指定自訂 Windows CNG 演算法,請建立包含演算法資訊的 CngCbcAuthenticatedEncryptorConfiguration 執行個體:

builder.Services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new CngCbcAuthenticatedEncryptorConfiguration
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // Passed to BCryptOpenAlgorithmProvider
        HashAlgorithm = "SHA256",
        HashAlgorithmProvider = null
    });

Note

對稱區塊加密演算法的金鑰長度必須是 > = 128 位元、區塊大小 >= 64 位元,而且必須使用 PKCS #7 填補支援 CBC 模式加密。 雜湊演算法的摘要大小必須為 > = 128 位元,且必須支援以 BCRYPT_ALG_HANDLE_HMAC_FLAG 旗標開啟。 *Provider 屬性可以設定為 null,以針對指定的演算法使用預設提供者。 如需詳細資訊,請參閱 BCryptOpenAlgorithmProvider 文件。

若要使用 Galois/Counter 模式加密搭配驗證來指定自訂 Windows CNG 演算法,請建立包含演算法資訊的 CngGcmAuthenticatedEncryptorConfiguration 執行個體:

builder.Services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new CngGcmAuthenticatedEncryptorConfiguration
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256
    });

Note

對稱區塊加密演算法的金鑰長度必須為 >= 128 位元、區塊大小正好為 128 位元,且必須支援 GCM 加密。 您可以將 EncryptionAlgorithmProvider 屬性設定為 null,以使用指定演算法的預設提供者。 如需詳細資訊,請參閱 BCryptOpenAlgorithmProvider 文件。

指定其他自訂演算法

雖然資料保護系統未作為第一級的 API,但其可擴展性足以允許指定幾乎任何類型的演算法。 例如,可以保留硬體安全模組 (HSM) 內含的所有金鑰,並提供核心加密和解密常式的自訂實作。 如需詳細資訊,請參閱 IAuthenticatedEncryptor中的

在 Docker 容器中運行時保存金鑰

Docker 容器中裝載時,應以下列其中一項中維護金鑰:

  • 在 Docker 中作為持久化磁碟區的文件夾,這些磁碟區的存在超過容器的生命周期,例如共享磁碟區或主機掛載的磁碟區。
  • 外部提供者,例如 Azure Blob 儲存體 (如 ProtectKeysWithAzureKeyVault 區段所示) 或 Redis

使用 Redis 保存金鑰

只應使用支援 Redis 資料持續性的 Redis 版本來儲存金鑰。 Azure Blob 儲存體是持續性的,可用來儲存金鑰。 如需詳細資訊,請參閱這個 GitHub 問題。

Logging

請啟用Information日誌或較低層級的日誌來診斷問題。 下列 appsettings.json 檔案會啟用資料保護 API 的資訊記錄:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.DataProtection": "Information"
    }
  },
  "AllowedHosts": "*"
}

如需記錄的詳細資訊,請參閱 在 .NET 和 ASP.NET Core 中記錄

其他資源

當資料保護系統初始化時,其會根據操作環境套用預設設定。 這些設定適用於在單一機器上執行的應用程式。 不過,在某些情況下,開發人員可能會想要變更預設設定:

  • 應用程式會分散到多部機器。
  • 基於合規性考慮。

在這些案例中,資料保護系統提供豐富的組態 API。

Warning

與組態檔類似,資料保護金鑰通道應使用適當的權限加以保護。 您可以選擇待用加密密鑰,但這不會防止網路攻擊者建立新的密鑰。 因此,您的應用程式的安全性會受到影響。 使用資料保護所設定的儲存位置應受限於應用程式本身的存取,類似於您保護組態檔的方式。 例如,如果您選擇將鑰匙圈儲存在磁碟上,請使用檔案系統權限。 請確定只有 Web 應用程式執行所在的身分識別具有該目錄的讀取、寫入和建立存取權。 如果您使用 Azure Blob 儲存體,則只有 Web 應用程式才能夠在 Blob 儲存體中讀取、寫入或建立新專案。

擴充方法 AddDataProtection 會傳回一個 IDataProtectionBuilder,其會公開您可以連結在一起以設定數據保護選項的擴充方法。

本文中使用的資料保護延伸模組需要下列 NuGet 封裝:

Note

如需將套件新增至 .NET 應用程式的指引,請參閱 套件取用工作流程 (NuGet 文件) 下的安裝和管理套件相關文章。 在 NuGet.org確認正確的套件版本。

使用 Azure Key Vault 保護金鑰 (ProtectKeysWithAzureKeyVault

若要使用開發人員認證在 本機與 Azure Key Vault 互動,請在 Visual Studio 中登入您的記憶體帳戶,或使用 Azure CLI 登入。 如果您尚未安裝 Azure CLI,請參閱 如何安裝 Azure CLI。 當您不使用 Visual Studio 時,您可以在 Visual Studio 的開發人員 PowerShell 面板或命令殼層中執行下列命令:

az login

如需詳細資訊,請參閱 使用開發人員工具登入 Azure

在 Entra 或 Azure 入口網站中建立金鑰保存庫時:

  • 將金鑰保存庫設定為使用 Azure 角色型存取控制 (RABC)。 如果您未在 Azure 虛擬網路上運行,包括用於本機開發和測試,請確認在 網路步驟中公用存取已啟用。 啟用公用存取只會公開金鑰保存庫端點。 存取仍然需要已驗證的帳戶。

  • 建立 Azure 受控 Identity 角色(或將角色新增至您打算使用的現有受控 Identity 角色),並搭配 Key Vault 密碼編譯使用者 角色。 將受控Identity指派給裝載部署的 Azure App Service:設定>Identity>使用者指派>新增

    Note

    如果您也計畫在本機使用授權的使用者以取得 Blob 存取來執行應用程式,且使用 Azure CLI 或 Visual Studio 的 Azure 服務驗證,請在 訪問控制 (IAM) 中,新增您的開發人員 Azure 用戶帳戶,並賦予 Key Vault 密碼編譯使用者 角色。 如果您想要透過Visual Studio使用 Azure CLI,請從開發人員 PowerShell 面板執行 az login 命令,並遵循提示向租用戶進行驗證。

  • 當金鑰加密作用中時,金鑰檔案中的金鑰會包含批注「This key is encrypted with Azure Key Vault.」。啟動應用程式之後,請從金鑰列結尾的內容選單中選取檢視/編輯命令,以確認金鑰存在並已套用金鑰保存庫的安全性。

  • 您可以選擇性地啟用自動金鑰庫金鑰輪替,而不必擔心需要使用基於過期或輪替的金鑰庫金鑰來解密承載的資料。 每個產生的數據保護金鑰都包含用來加密金鑰保存庫金鑰的參考。 只要確定您保留過期的金鑰保存庫金鑰,請勿將其刪除在密鑰保存庫中。 此外,請在應用程式的金鑰保存庫組態中使用無版本金鑰標識碼,其中標識元結尾不會放置任何密鑰 GUID(例如: https://contoso.vault.azure.net/keys/data-protection)。 針對兩個金鑰使用類似的輪替期間,金鑰保存庫金鑰會比數據保護密鑰更頻繁地輪替,以確保在數據保護密鑰輪替時使用新的金鑰保存庫金鑰。

使用 Azure Key Vault 保護金鑰,實作了IXmlEncryptor,它會停用自動資料保護設定,包括停用金鑰環的儲存位置。 若要將 Azure Blob 記憶體提供者設定為將金鑰儲存在 Blob 記憶體中,請遵循 ASP.NET Core 中密鑰記憶體提供者中的 指引,並在應用程式中呼叫其中 PersistKeysToAzureBlobStorage 一個多載。 下列範例會使用接受 Blob URI 和令牌認證的多載TokenCredential,依賴 Azure 受控Identity 進行角色為基礎的存取控制(RBAC)。

若要設定 Azure Key Vault 提供者,請呼叫其中一個 ProtectKeysWithAzureKeyVault 的多載函式。 下列範例會使用接受密鑰標識碼和令牌憑證的多載,TokenCredential 依賴於生產環境中的 Managed Identity 以 RBAC 進行操作,或在開發和測試期間使用 ManagedIdentityCredential。 其他重載可接受金鑰保存庫客戶端或具有客戶端密碼的應用程式客戶端識別碼。 如需詳細資訊,請參閱 ASP.NET Core 中的金鑰儲存提供者

如需 Azure SDK API 和驗證的詳細資訊,請參閱 使用 Azure 連結庫向 Azure Identity 服務驗證 .NET 應用程式 ,並使用 Azure 角色型存取控制提供 Key Vault 金鑰、憑證和秘密的存取權。 如需記錄指引,請參閱 使用適用於 .NET 的 Azure SDK 進行記錄:不使用客戶端註冊進行記錄。 對於使用相依性注入的應用程式,應用程式可以呼叫 AddAzureClientsCore,並將 true 作為 enableLogForwarding 傳遞,以建立和配置日誌基礎架構。

若要在 Azure 入口網站中建立金鑰,請參閱 快速入門:使用 Azure 入口網站從 Azure 金鑰保存庫設定和擷取金鑰。 至少給金鑰 GetUnwrap KeyWrap Key 權限。 記錄金鑰識別碼以用於應用程式的設定。 如果您打算啟用金鑰保存庫金鑰的自動輪替,請記錄 無版本 金鑰識別碼,其中不會將金鑰 GUID 放在識別碼結尾 (例如: https://contoso.vault.azure.net/keys/data-protection)。

在註冊服務的檔案Program中:

TokenCredential? credential;

if (builder.Environment.IsProduction())
{
    credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
    // Local development and testing only
    DefaultAzureCredentialOptions options = new()
    {
        // Specify the tenant ID to use the dev credentials when running the app locally
        // in Visual Studio.
        VisualStudioTenantId = "{TENANT ID}",
        SharedTokenCacheTenantId = "{TENANT ID}"
    };

    credential = new DefaultAzureCredential(options);
}

services.AddDataProtection()
    .SetApplicationName("{APPLICATION NAME}")
    .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
    .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);

{MANAGED IDENTITY CLIENT ID}:Azure 託管的 Identity 客戶端識別碼 (GUID)。

{TENANT ID}:租使用者標識碼。

{APPLICATION NAME}SetApplicationName 設定資料保護系統中此應用程式的唯一名稱。 應用程式部署間的值應保持一致。

{BLOB URI}:金鑰檔案的完整 URI。 當您建立密鑰檔案時,Azure 記憶體會產生 URI。 請勿使用 SAS。

{KEY IDENTIFIER}:用於密鑰加密的 Azure Key Vault 金鑰標識碼。 存取原則可讓應用程式使用 GetUnwrap KeyWrap Key 許可權存取金鑰保存庫。 建立金鑰後,可以從 Entra 或 Azure 入口網站中的金鑰取得金鑰版本。 如果您啟用金鑰保存庫金鑰的自動輪替,請確定您在應用程式的金鑰保存庫設定中使用 無版本 金鑰識別碼,其中不會將金鑰 GUID 放在識別碼結尾 (範例: https://contoso.vault.azure.net/keys/data-protection)。

若要讓應用程式與 Azure Key Vault 進行通訊和授權, Azure.Identity 應用程式必須參考 NuGet 套件

Note

如需將套件新增至 .NET 應用程式的指引,請參閱 套件取用工作流程 (NuGet 文件) 下的安裝和管理套件相關文章。 在 NuGet.org確認正確的套件版本。

Note

在非生產環境中,上述範例會使用 DefaultAzureCredential 來簡化驗證,同時開發部署至 Azure 的應用程式,方法是將 Azure 主控環境中所使用的認證與本機開發中使用的認證結合在一起。 如需詳細資訊,請參閱 使用系統指派的受控識別向 Azure 資源驗證 Azure 裝載的 .NET 應用程式

如果應用程式使用舊版 Azure 套件 (Microsoft.AspNetCore.DataProtection.AzureStorageMicrosoft.AspNetCore.DataProtection.AzureKeyVault),建議您 移除 這些參考並升級至 Azure.Extensions.AspNetCore.DataProtection.BlobsAzure.Extensions.AspNetCore.DataProtection.Keys 套件。 較新的套件可解決重要的安全性和穩定性問題。

替代的共用存取簽章(SAS)方法:作為透過受控 Identity 存取 Azure Blob 儲存體中密鑰 Blob 的替代方法,您可以呼叫 PersistKeysToAzureBlobStorage,它可接受包含 SAS 令牌的 Blob URI 的多載。 下列範例將繼續使用 ManagedIdentityCredential (production,生產環境)或 DefaultAzureCredential (development,開發及測試環境)作為其 TokenCredential,如前述範例所示。

services.AddDataProtection()
    .SetApplicationName("{APPLICATION NAME}")
    .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
    .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);

{APPLICATION NAME}SetApplicationName 設定資料保護系統中此應用程式的唯一名稱。 應用程式部署間的值應保持一致。

{BLOB URI WITH SAS}:金鑰檔案應存放的完整 URI,其中包含作為查詢字串參數的 SAS 令牌。 當您要求為上傳的密鑰檔案生成 SAS 時,Azure 儲存會產生 URI。

{KEY IDENTIFIER}:用於密鑰加密的 Azure Key Vault 金鑰標識碼。 存取原則可讓應用程式使用 GetUnwrap KeyWrap Key 許可權存取金鑰保存庫。 建立金鑰後,可以從 Entra 或 Azure 入口網站中的金鑰取得金鑰版本。 如果您啟用金鑰保存庫金鑰的自動輪替,請確定您在應用程式的密鑰保存庫組態中使用無版本金鑰標識碼,其中沒有將密鑰 GUID 放在標識子結尾(例如: https://contoso.vault.azure.net/keys/data-protection)。

將金鑰儲存到檔案系統 (PersistKeysToFileSystem

若要將金鑰儲存在 UNC 共用上,而不是儲存在 %LOCALAPPDATA% 的預設位置,請使用 PersistKeysToFileSystem 設定系統:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
}

Warning

如果您變更金鑰持續性位置,系統就不會再自動加密待用密鑰,因為它不知道 DPAPI 是否為適當的加密機制。

在資料庫中儲存金鑰 (PersistKeysToDbContext

若要使用 EntityFramework 將金鑰儲存在資料庫中,請使用 Microsoft.AspNetCore.DataProtection.EntityFrameworkCore 封裝來設定系統:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToDbContext<DbContext>()
}

上述程式碼會將金鑰儲存在設定的資料庫中。 所使用的資料庫內容必須實作 IDataProtectionKeyContextIDataProtectionKeyContext 會公開屬性 DataProtectionKeys

public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }

這個屬性代表儲存索引鍵的資料表。 手動建立資料表,或使用 DbContext 遷移功能建立資料表。 如需詳細資訊,請參閱DataProtectionKey

保護金鑰設定 API (ProtectKeysWith\*

您可以透過呼叫任何 ProtectKeysWith\* 設定 API 來配置系統以保護靜態的金鑰。 請考慮下列範例,它會將密鑰儲存在 UNC 共用上,並使用特定的 X.509 憑證加密待用密鑰:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
        .ProtectKeysWithCertificate(Configuration["Thumbprint"]);
}

您可以提供 X509Certificate2ProtectKeysWithCertificate,例如從檔案載入的憑證:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
        .ProtectKeysWithCertificate(
            new X509Certificate2("certificate.pfx", Configuration["Thumbprint"]));
}

如需內建密鑰加密機制的更多範例和討論,請參閱 使用 ASP.NET Core 在 Windows 和 Azure 中待用密鑰加密

使用任何憑證解除保護金鑰 (UnprotectKeysWithAnyCertificate

您可以使用由X509Certificate2UnprotectKeysWithAnyCertificate組成的憑證陣列來輪替憑證及解密待用密鑰。

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
        .ProtectKeysWithCertificate(
            new X509Certificate2("certificate.pfx", Configuration["MyPasswordKey"));
        .UnprotectKeysWithAnyCertificate(
            new X509Certificate2("certificate_old_1.pfx", Configuration["MyPasswordKey_1"]),
            new X509Certificate2("certificate_old_2.pfx", Configuration["MyPasswordKey_2"]));
}

設定預設金鑰存留期 (SetDefaultKeyLifetime

若要將系統設定為使用 14 天而不是預設 90 天的金鑰存留期,請使用 SetDefaultKeyLifetime

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}

設定應用程式名稱 (SetApplicationName

根據預設,資料保護系統會根據應用程式的內容根目錄路徑相互隔離,即使它們共用相同的實體金鑰存放庫也是如此。 此隔離可防止應用程式理解彼此的受保護承載。

若要在應用程式之間共用受保護的承載:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .SetApplicationName("{APPLICATION NAME}");
}

SetApplicationName 在內部設定了 DataProtectionOptions.ApplicationDiscriminator。 如需如何使用鑑別子的詳細資訊,請參閱本文後續的章節:

停用自動產生金鑰 (DisableAutomaticKeyGeneration

您可能會遇到這樣的案例:不希望應用程式自動滾動金鑰(建立新金鑰),因為金鑰即將到期。 這種情況的一個例子可能是以主次關係設定的應用程式,其中只有主應用程式負責密鑰管理,而次要應用程式僅具有密鑰環的唯讀檢視。 藉由 DisableAutomaticKeyGeneration 設定系統,可以將次要應用程式設定為將金鑰環視為唯讀:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .DisableAutomaticKeyGeneration();
}

每個應用程式的隔離

當資料保護系統由 ASP.NET Core 主機提供時,其會自動將應用程式相互隔離,即使這些應用程式是在相同的背景工作處理序帳戶下執行,且使用相同的主要金鑰資料也一樣。 這類似於 System.Web 的 <machineKey> 元素中之 IsolateApps 修飾元。

隔離機制的運作方式是將本機電腦上的每個應用程式視為唯一租用戶,因此任何指定應用程式的根目錄 IDataProtector 會自動將應用程式識別碼納入為鑑別子 (ApplicationDiscriminator)。 應用程式的唯一識別碼是應用程式的實體路徑:

  • 針對裝載於 IIS 的應用程式,唯一識別碼是應用程式的 IIS 實體路徑。 如果應用程式部署在 Web 服務器陣列環境中,則此值是穩定的 (假設 IIS 環境在 Web 服務器陣列中的所有機器上都以相似的方式進行設定)。
  • 對於在 Kestrel 伺服器上執行的自我裝載應用程式,唯一識別碼是磁碟上應用程式的實體路徑。

唯一識別碼的設計目的是要能夠在重設之後繼續存在,無論是應用程式本身重設還是整個機器重設。

此隔離機制假設應用程式不具惡意。 惡意應用程式可能會影響在相同工作流程帳戶下執行的任何其他應用程式。 在應用程式互不受信任的共用裝載環境中,裝載提供者應採取步驟確保應用程式之間的作業系統層級隔離,包括分隔應用程式的基礎金鑰存放庫。

如果 ASP.NET Core 主機未提供資料保護系統 (例如,如果您透過 DataProtectionProvider 具體類型具現化該保護系統),則根據預設,系統會停用應用程式隔離。 停用應用程式隔離時,只要應用程式提供適當的目的,則相同金鑰資料支援的所有應用程式都可以共用承載。 若要在此環境中提供應用程式隔離,請在組態物件上呼叫 SetApplicationName 方法,並為每個應用程式提供唯一的名稱。

資料保護和應用程式隔離

針對應用程式隔離,請考慮下列幾點:

  • 當多個應用程式指向相同的金鑰存放庫時,目的是讓這些應用程式共用相同的主要金鑰資料。 資料保護的開發假設是,所有共用金鑰通道的應用程式都可以存取該金鑰通道中的所有項目。 應用程式唯一識別碼可用來隔離衍生自金鑰通道所提供金鑰的應用程式特定金鑰。 不期望使用項目層級的權限,例如 Azure KeyVault 所提供的,用於強制實施額外的隔離。 嘗試項目層級權限會產生應用程式錯誤。 如果您不想依賴內建應用程式隔離,則應該使用個別的金鑰存放區位置,而不使在應用程式之間共用。

  • 應用程式鑑別子 (ApplicationDiscriminator) 用於允許不同的應用程式共用相同的主要金鑰資料,並以維持其加密載荷彼此區別。 若要讓應用程式能夠讀取彼此的密碼編譯承載,其必須具有相同的應用程式鑑別子,這可以藉由呼叫 SetApplicationName 進行設定。

  • 如果應用程式遭到入侵(例如,透過 RCE 攻擊),則該應用程式可存取的所有主要密鑰數據也必須被視為遭到入侵,而不論其待用保護狀態為何。 這表示,如果兩個應用程式指向相同的存放庫,即使它們使用不同的應用程式鑑別子,只要一個應用程式遭到入侵,在功能上皆等同於兩者遭到入侵。

    即使這兩個應用程式使用不同的機制來保護靜態密鑰,這個「功能上相當於兩者妥協的」條款仍然適用。 一般而言,這不是預期的設定。 待用保護機制的目的是在網路攻擊者取得存放庫的讀取存取權時提供保護。 取得存放庫寫入權限的網路攻擊者 (可能是因為其在應用程式內取得程式碼執行權限) 可向儲存體中插入惡意金鑰。 資料保護系統故意不提供保護,以防止網路攻擊者取得對金鑰存放庫的寫入存取。

  • 如果應用程式之間需要保持真正的隔離,則應使用不同的金鑰存放庫。 這自然脫離了「隔離」的定義。 如果應用程式具有彼此資料存放區的讀取和寫入存取,則不會進行隔離。

更改演算法 UseCryptographicAlgorithms

資料保護堆疊可讓您變更新產生金鑰所使用的預設演算法。 若要這樣做,最簡單的方法是從組態回撥呼叫 UseCryptographicAlgorithms

services.AddDataProtection()
    .UseCryptographicAlgorithms(
        new AuthenticatedEncryptorConfiguration()
    {
        EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
        ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
    });

預設 EncryptionAlgorithm 為 AES-256-CBC,而預設 ValidationAlgorithm 為 HMACSHA256。 預設原則可由系統管理員透過全機器原則設定,但針對 UseCryptographicAlgorithms 的明確呼叫會覆寫預設原則。

呼叫 UseCryptographicAlgorithms 可讓您從預先定義的內建清單中指定所需的演算法。 您不需要擔心演算法的實作。 在上述案例中,若是 Windows 上執行,則資料保護系統會嘗試使用 AES 的 CNG 實作。 否則,其會回復為受控 System.Security.Cryptography.Aes 類別。

您可以透過呼叫 UseCustomCryptographicAlgorithms 來手動指定實作。

Tip

變更演算法不會影響金鑰通道中的現有金鑰。 其只會影響新產生的金鑰。

指定自訂受控演算法

若要指定自訂受控演算法,請建立指向實作類型的 ManagedAuthenticatedEncryptorConfiguration 執行個體:

serviceCollection.AddDataProtection()
    .UseCustomCryptographicAlgorithms(
        new ManagedAuthenticatedEncryptorConfiguration()
    {
        // A type that subclasses SymmetricAlgorithm
        EncryptionAlgorithmType = typeof(Aes),

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // A type that subclasses KeyedHashAlgorithm
        ValidationAlgorithmType = typeof(HMACSHA256)
    });

一般而言,*Type 屬性必須指向 SymmetricAlgorithmKeyedHashAlgorithm 的具體、可具現化 (透過公用無參數的建構函式) 實作,不過為了方便起見,系統針對某些值 (例如,typeof(Aes)) 進行了特殊處理。

Note

SymmetricAlgorithm 的金鑰長度必須 ≥ 128 位元,區塊大小 ≥ 64 位元,且必須支援使用 PKCS #7 填補的 CBC 模式加密。 KeyedHashAlgorithm 的雜湊大小必須為 >= 128 位元,且必須支援長度等於雜湊演算法雜湊長度的金鑰。 KeyedHashAlgorithm 並非必須為 HMAC。

指定自訂 Windows CNG 演算法

若要使用 CBC 模式加密搭配 HMAC 驗證來指定自訂 Windows CNG 演算法,請建立包含演算法資訊的 CngCbcAuthenticatedEncryptorConfiguration 執行個體:

services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(
        new CngCbcAuthenticatedEncryptorConfiguration()
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // Passed to BCryptOpenAlgorithmProvider
        HashAlgorithm = "SHA256",
        HashAlgorithmProvider = null
    });

Note

對稱區塊加密演算法的金鑰長度必須是 > = 128 位元、區塊大小 >= 64 位元,而且必須使用 PKCS #7 填補支援 CBC 模式加密。 雜湊演算法的摘要大小必須為 > = 128 位元,且必須支援以 BCRYPT_ALG_HANDLE_HMAC_FLAG 旗標開啟。 *Provider 屬性可以設定為 null,以針對指定的演算法使用預設提供者。 如需詳細資訊,請參閱 BCryptOpenAlgorithmProvider 文件。

若要使用 Galois/Counter 模式加密搭配驗證來指定自訂 Windows CNG 演算法,請建立包含演算法資訊的 CngGcmAuthenticatedEncryptorConfiguration 執行個體:

services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(
        new CngGcmAuthenticatedEncryptorConfiguration()
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256
    });

Note

對稱區塊加密演算法的金鑰長度必須為 >= 128 位元、區塊大小正好為 128 位元,且必須支援 GCM 加密。 您可以將 EncryptionAlgorithmProvider 屬性設定為 null,以使用指定演算法的預設提供者。 如需詳細資訊,請參閱 BCryptOpenAlgorithmProvider 文件。

指定其他自訂演算法

雖然資料保護系統未作為第一級的 API,但其可擴展性足以允許指定幾乎任何類型的演算法。 例如,可以保留硬體安全模組 (HSM) 內含的所有金鑰,並提供核心加密和解密常式的自訂實作。 如需詳細資訊,請參閱 IAuthenticatedEncryptor中的

在 Docker 容器中運行時保存金鑰

Docker 容器中裝載時,應以下列其中一項中維護金鑰:

使用 Redis 保存金鑰

只應使用支援 Redis 資料持續性的 Redis 版本來儲存金鑰。 Azure Blob 儲存體是持續性的,可用來儲存金鑰。 如需詳細資訊,請參閱這個 GitHub 問題。

Logging

請啟用Information日誌或較低層級的日誌來診斷問題。 下列 appsettings.json 檔案會啟用資料保護 API 的資訊記錄:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.DataProtection": "Information"
    }
  }
}

如需記錄的詳細資訊,請參閱 在 .NET 和 ASP.NET Core 中記錄

其他資源