ASP.NET Core 中的数据保护密钥管理和生存期信息

作者:Rick Anderson

密钥管理

应用尝试检测其操作环境并自行处理密钥配置。

  1. 如果应用托管在 Azure 应用中,密钥将保存在 %HOME%\ASP.NET\DataProtection-Keys 文件夹中。 此文件夹由网络存储提供支持,并跨托管应用的所有计算机同步。

    • 密钥不是 rest 保护的。
    • DataProtection-Keys 文件夹向单个部署槽位中应用的所有实例提供密钥环。
    • 各部署槽位(例如过渡槽和生成槽)不共享密钥环。 在部署槽位之间交换时,例如从过渡交换到生产或使用 A/B 测试,任何使用数据保护的应用都无法使用之前槽位中的密钥环来解密存储的数据。 这会导致用户退出使用标准 ASP.NET Core cookie 身份验证的应用,因为它使用数据保护保护其 Cookie。 如果需要与槽位无关的密钥环,请使用外部密钥环提供程序,例如 Azure Blob 存储、Azure Key Vault、SQL 存储或 Redis 缓存。
  2. 如果用户配置文件可用,密钥将保存到 %LOCALAPPDATA%\ASP.NET\DataProtection-Keys 文件夹中。 如果操作系统是 Windows,则使用 DPAPI 对密钥进行 rest 加密。

    同时还必须启用应用池的 setProfileEnvironment attributesetProfileEnvironment 的默认值为 true。 在某些情况下(例如,Windows 操作系统),将 setProfileEnvironment 设置为 false。 如果密钥未按预期存储在用户配置文件目录中,请执行以下操作:

    1. 导航到 %windir%/system32/inetsrv/config 文件夹。
    2. 打开 applicationHost.config 文件。
    3. 查找 <system.applicationHost><applicationPools><applicationPoolDefaults><processModel> 元素。
    4. 确认 setProfileEnvironment 属性不存在,这会将值默认设置为 true,或者将属性的值显式设置为 true
  3. 如果应用托管在 IIS 中,密钥将保存到 HKLM 注册表的特殊注册表项中,该注册表项仅列在工作进程帐户的 ACL 中。 使用 DPAPI 对密钥 rest 加密。

  4. 如果这些条件都不匹配,则密钥不会保存在当前进程之外。 当进程关闭时,生成的所有密钥都将丢失。

开发人员始终拥有完全控制权,并且可以替代密钥的存储方式和存储位置。 上面的前三个选项应该为大多数应用提供良好的默认值,类似于 ASP.NET <machineKey> 自动生成例程过去的工作方式。 最后的回退选项是唯一需要开发人员在想要保存密钥时预先指定配置的方案,但此回退仅在极少数情况下发生。

在 Docker 容器中托管时,密钥应保存在作为 Docker 卷(在容器生存期过后仍然存在的共享卷或主机装载的卷)的文件夹中或外部提供程序中,例如 Azure Key VaultRedis。 外部提供程序在应用无法访问共享网络卷的 Web 场方案中也很有用(有关详细信息,请参阅 PersistKeysToFileSystem)。

警告

如果开发人员替代上述规则并将数据保护系统指向特定的密钥存储库,则会禁用密钥的自动静态加密。 可以通过配置重新启用 rest 保护。

密钥生存期

默认情况下,密钥的生存期为 90 天。 当密钥过期时,应用会自动生成一个新密钥并将新密钥设置为活动密钥。 只要停用的密钥保留在系统上,应用就可以解密受这些密钥保护的任何数据。 有关详细信息,请参阅密钥管理

默认算法

使用的默认有效负载保护算法为 AES-256-CBC(保证机密性)和 HMACSHA256(保证真实性)。 系统使用每 90 天更改一次的 512 位主密钥,根据每个有效负载派生用于这些算法的两个子密钥。 有关详细信息,请参阅子密钥派生

删除密钥

删除密钥会使其受保护的数据永久不可访问。 为了降低这种风险,建议不要删除密钥。 密钥的累积通常影响最小,因为它们很小。 在特殊情况下(例如运行时间极长的服务)可以删除密钥。 仅删除密钥:

  • 旧的(不再使用)。
  • 当你可以接受数据丢失风险以换取存储节省时。

建议不要删除数据保护密钥。

using Microsoft.AspNetCore.DataProtection.KeyManagement;

var services = new ServiceCollection();
services.AddDataProtection();

var serviceProvider = services.BuildServiceProvider();

var keyManager = serviceProvider.GetService<IKeyManager>();

if (keyManager is IDeletableKeyManager deletableKeyManager)
{
    var utcNow = DateTimeOffset.UtcNow;
    var yearAgo = utcNow.AddYears(-1);

    if (!deletableKeyManager.DeleteKeys(key => key.ExpirationDate < yearAgo))
    {
        Console.WriteLine("Failed to delete keys.");
    }
    else
    {
        Console.WriteLine("Old keys deleted successfully.");
    }
}
else
{
    Console.WriteLine("Key manager does not support deletion.");
}

其他资源

密钥管理

应用尝试检测其操作环境并自行处理密钥配置。

  1. 如果应用托管在 Azure 应用中,密钥将保存在 %HOME%\ASP.NET\DataProtection-Keys 文件夹中。 此文件夹由网络存储提供支持,并跨托管应用的所有计算机同步。

    • 密钥不是 rest 保护的。
    • DataProtection-Keys 文件夹向单个部署槽位中应用的所有实例提供密钥环。
    • 各部署槽位(例如过渡槽和生成槽)不共享密钥环。 在部署槽位之间交换时,例如从过渡交换到生产或使用 A/B 测试,任何使用数据保护的应用都无法使用之前槽位中的密钥环来解密存储的数据。 这会导致用户退出使用标准 ASP.NET Core cookie 身份验证的应用,因为它使用数据保护保护其 Cookie。 如果需要与槽位无关的密钥环,请使用外部密钥环提供程序,例如 Azure Blob 存储、Azure Key Vault、SQL 存储或 Redis 缓存。
  2. 如果用户配置文件可用,密钥将保存到 %LOCALAPPDATA%\ASP.NET\DataProtection-Keys 文件夹中。 如果操作系统是 Windows,则使用 DPAPI 对密钥进行 rest 加密。

    同时还必须启用应用池的 setProfileEnvironment attributesetProfileEnvironment 的默认值为 true。 在某些情况下(例如,Windows 操作系统),将 setProfileEnvironment 设置为 false。 如果密钥未按预期存储在用户配置文件目录中,请执行以下操作:

    1. 导航到 %windir%/system32/inetsrv/config 文件夹。
    2. 打开 applicationHost.config 文件。
    3. 查找 <system.applicationHost><applicationPools><applicationPoolDefaults><processModel> 元素。
    4. 确认 setProfileEnvironment 属性不存在,这会将值默认设置为 true,或者将属性的值显式设置为 true
  3. 如果应用托管在 IIS 中,密钥将保存到 HKLM 注册表的特殊注册表项中,该注册表项仅列在工作进程帐户的 ACL 中。 使用 DPAPI 对密钥 rest 加密。

  4. 如果这些条件都不匹配,则密钥不会保存在当前进程之外。 当进程关闭时,生成的所有密钥都将丢失。

开发人员始终拥有完全控制权,并且可以替代密钥的存储方式和存储位置。 上面的前三个选项应该为大多数应用提供良好的默认值,类似于 ASP.NET <machineKey> 自动生成例程过去的工作方式。 最后的回退选项是唯一需要开发人员在想要保存密钥时预先指定配置的方案,但此回退仅在极少数情况下发生。

在 Docker 容器中托管时,密钥应保存在作为 Docker 卷(在容器生存期过后仍然存在的共享卷或主机装载的卷)的文件夹中或外部提供程序中,例如 Azure Key VaultRedis。 外部提供程序在应用无法访问共享网络卷的 Web 场方案中也很有用(有关详细信息,请参阅 PersistKeysToFileSystem)。

警告

如果开发人员替代上述规则并将数据保护系统指向特定的密钥存储库,则会禁用密钥的自动静态加密。 可以通过配置重新启用 rest 保护。

密钥生存期

默认情况下,密钥的生存期为 90 天。 当密钥过期时,应用会自动生成一个新密钥并将新密钥设置为活动密钥。 只要停用的密钥保留在系统上,应用就可以解密受这些密钥保护的任何数据。 有关详细信息,请参阅密钥管理

默认算法

使用的默认有效负载保护算法为 AES-256-CBC(保证机密性)和 HMACSHA256(保证真实性)。 系统使用每 90 天更改一次的 512 位主密钥,根据每个有效负载派生用于这些算法的两个子密钥。 有关详细信息,请参阅子密钥派生

其他资源