配置 ASP.NET Core 数据保护Configure ASP.NET Core Data Protection

  • 应用程序分布在多台计算机上。
  • 出于合规性原因。

在这些情况下,数据保护系统提供了丰富的配置 API。

警告

与配置文件类似,应使用适当的权限保护数据保护密钥环。你可以选择对静态密钥加密,但这不会阻止攻击者创建新密钥。因此,应用的安全将受到影响。使用数据保护配置的存储位置应该将其访问权限限制为应用本身,这与保护配置文件的方式类似。例如,如果选择将密钥环存储在磁盘上,请使用文件系统权限。确保你的 web 应用在其下运行的标识具有对该目录的读取、写入和创建访问权限。如果使用 Azure Blob 存储,则只有 web 应用应能够在 Blob 存储中读取、写入或创建新条目等。

扩展方法返回IDataProtectionBuilder 公开扩展方法,你可以将这些方法链接在一起来配置数据保护选项。

本文中使用的数据保护扩展插件需要以下 NuGet 包:

若要在中存储密钥,请在 Startup 类中配置ProtectKeysWithAzureKeyVault的系统:

设置密钥环存储位置(例如, )。必须设置位置,因为调用 ProtectKeysWithAzureKeyVault 实现了禁用自动数据保护设置的IXmlEncryptor ,包括密钥环存储位置。前面的示例使用 Azure Blob 存储来持久保存密钥环。有关详细信息,请参阅。还可以通过PersistKeysToFileSystem将密钥环保存到本地。

keyIdentifier 是用于密钥加密的密钥保管库密钥标识符。例如,在 contosokeyvault 中名为 dataprotection 的密钥保管库中创建的密钥具有密钥标识符 向应用提供对密钥保管库的解包密钥包装密钥权限。

ProtectKeysWithAzureKeyVault 重载:

PersistKeysToFileSystemPersistKeysToFileSystem

若要将密钥存储在 UNC 共享上,而不是存储在 % LOCALAPPDATA% 默认位置,请使用PersistKeysToFileSystem配置系统:

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

警告

如果更改密钥持久性位置,系统将不再自动加密静态密钥,因为它不知道 DPAPI 是否为适当的加密机制。

ProtectKeysWithProtectKeysWith

可以通过调用ProtectKeysWith*配置 api,将系统配置为保护静态密钥。请考虑以下示例,该示例将密钥存储在 UNC 共享上,并使用特定的 x.509 证书对静态密钥进行加密:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddDataProtection()
  4. .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
  5. .ProtectKeysWithCertificate("thumbprint");
  6. }

在 ASP.NET Core 2.1 或更高版本中,你可以提供的X509Certificate2 ,例如从文件中加载的证书:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddDataProtection()
  4. .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
  5. .ProtectKeysWithCertificate(
  6. new X509Certificate2("certificate.pfx", "password"));
  7. }

有关内置密钥加密机制的更多示例和讨论,请参阅。

UnprotectKeysWithAnyCertificateUnprotectKeysWithAnyCertificate

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddDataProtection()
  4. .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
  5. .ProtectKeysWithCertificate(
  6. .UnprotectKeysWithAnyCertificate(
  7. new X509Certificate2("certificate_old_1.pfx", "password_1"),
  8. new X509Certificate2("certificate_old_2.pfx", "password_2"));
  9. }

若要将系统配置为使用14天的密钥生存期而不是默认的90天,请使用:

SetApplicationNameSetApplicationName

默认情况下,数据保护系统基于其路径将应用彼此隔离,即使它们共享相同的物理密钥存储库。这可防止应用了解彼此的受保护负载。

在应用之间共享受保护的负载:

  • 用相同的值在每个应用中配置 SetApplicationName
  • 在应用程序中使用相同版本的数据保护 API 堆栈。在应用的项目文件中执行以下任一操作:
    • 通过引用相同的共享框架版本。
    • 引用相同的数据保护包版本。
  1. public void ConfigureServices(IServiceCollection services)
  2. services.AddDataProtection()
  3. .SetApplicationName("shared app name");
  4. }

DisableAutomaticKeyGenerationDisableAutomaticKeyGeneration

您可能会遇到这样的情况:不希望应用程序在接近过期时自动滚动更新密钥(创建新的密钥)。这种情况的一个示例可能是在主/辅助关系中设置的应用,其中只有主应用负责密钥管理问题,辅助应用只是具有密钥环的只读视图。可以通过使用 DisableAutomaticKeyGeneration配置系统,将辅助应用配置为将密钥环视为只读:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddDataProtection()
  4. .DisableAutomaticKeyGeneration();
  5. }

每应用程序隔离Per-application isolation

数据保护系统提供了 ASP.NET Core 主机,但它自动隔离了从另一个,应用程序,即使这些应用在相同的工作进程帐户下运行,并且使用相同的主密钥材料。这有点类似于 IsolateApps 的 <machineKey> 元素中的修饰符。

隔离机制的工作原理是将本地计算机上的每个应用视为唯一的租户,因此,任何给定应用的根 IDataProtector 会自动将应用 ID 包含为鉴别器。应用的唯一 ID 是应用的物理路径:

  • 对于在 IIS 中托管的应用,唯一 ID 是应用的 IIS 物理路径。如果在 web 场环境中部署了应用,则此值是稳定的,假定在 web 场中的所有计算机上配置了类似的 IIS 环境。
  • 对于在上运行的自承载应用程序,唯一 ID 是指向磁盘上的应用程序的物理路径。

唯一标识符的设计目的是在每个应用程序和计算机本身—重置。

此隔离机制假定应用不是恶意的。恶意应用始终会影响在同一工作进程帐户下运行的任何其他应用。在应用不受信任的共享主机环境中,托管提供商应采取措施来确保应用之间的操作系统级隔离,包括分离应用程序的底层密钥存储库。

如果数据保护系统不是由 ASP.NET Core 主机提供的(例如,如果通过 DataProtectionProvider 具体类型对其进行实例化),则默认情况下禁用应用程序隔离。禁用应用隔离后,只要提供相应的用途,同一密钥材料支持的所有应用就可以共享有效负载。若要在此环境中提供应用隔离,请对配置对象调用方法,并为每个应用提供唯一的名称。

数据保护堆栈允许您更改新生成的密钥使用的默认算法。执行此操作的最简单方法是从配置回调调用UseCryptographicAlgorithms

  1. services.AddDataProtection()
  2. .UseCryptographicAlgorithms(
  3. new AuthenticatedEncryptorConfiguration()
  4. {
  5. EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
  6. ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
  7. });
  1. services.AddDataProtection()
  2. .UseCryptographicAlgorithms(
  3. new AuthenticatedEncryptionSettings()
  4. {
  5. EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
  6. ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
  7. });

默认 EncryptionAlgorithm 为 AES-256-CBC,默认 ValidationAlgorithm 为 HMACSHA256。系统管理员可以通过设置默认策略,但对 UseCryptographicAlgorithms 的显式调用会替代默认策略。

通过调用 UseCryptographicAlgorithms,可以从预定义的内置列表中指定所需的算法。您无需担心算法的实现。在上述方案中,如果在 Windows 上运行,数据保护系统将尝试使用 AES 的 CNG 实现。否则,它会回退到托管的系统。

可以通过调用手动指定实现。

提示

更改算法不会影响密钥环中的现有密钥。它仅影响新生成的键。

若要指定自定义托管算法,请创建一个指向实现类型的ManagedAuthenticatedEncryptionSettings实例:

  1. serviceCollection.AddDataProtection()
  2. .UseCustomCryptographicAlgorithms(
  3. new ManagedAuthenticatedEncryptionSettings()
  4. {
  5. // A type that subclasses SymmetricAlgorithm
  6. EncryptionAlgorithmType = typeof(Aes),
  7. // Specified in bits
  8. EncryptionAlgorithmKeySize = 256,
  9. // A type that subclasses KeyedHashAlgorithm
  10. ValidationAlgorithmType = typeof(HMACSHA256)

通常,*类型属性必须指向和KeyedHashAlgorithm的具体实例实例(通过公共无参数的 ctor)实现,尽管系统特别适用于一些值(如 )以方便使用。

备注

System.security.cryptography.symmetricalgorithm 必须具有≥128位的密钥长度和≥64位的块大小,并且必须支持 PKCS #7 填充的 CBC 模式加密。KeyedHashAlgorithm 的摘要大小必须为 > = 128 位,并且它必须支持长度等于哈希算法摘要长度的键。KeyedHashAlgorithm 不一定是 HMAC。

若要通过 HMAC 验证使用 CBC 模式加密指定自定义 Windows CNG 算法,请创建包含算法信息的实例:

  1. services.AddDataProtection()
  2. .UseCustomCryptographicAlgorithms(
  3. new CngCbcAuthenticatedEncryptorConfiguration()
  4. {
  5. // Passed to BCryptOpenAlgorithmProvider
  6. EncryptionAlgorithm = "AES",
  7. EncryptionAlgorithmProvider = null,
  8. // Specified in bits
  9. EncryptionAlgorithmKeySize = 256,
  10. // Passed to BCryptOpenAlgorithmProvider
  11. HashAlgorithm = "SHA256",
  12. HashAlgorithmProvider = null
  13. });

若要通过 HMAC 验证使用 CBC 模式加密指定自定义 Windows CNG 算法,请创建包含算法信息的CngCbcAuthenticatedEncryptionSettings实例:

  1. services.AddDataProtection()
  2. .UseCustomCryptographicAlgorithms(
  3. new CngCbcAuthenticatedEncryptionSettings()
  4. {
  5. // Passed to BCryptOpenAlgorithmProvider
  6. EncryptionAlgorithm = "AES",
  7. EncryptionAlgorithmProvider = null,
  8. // Specified in bits
  9. EncryptionAlgorithmKeySize = 256,
  10. // Passed to BCryptOpenAlgorithmProvider
  11. HashAlgorithm = "SHA256",
  12. HashAlgorithmProvider = null
  13. });

备注

对称块加密算法的密钥长度必须为 > = 128 位,块大小为 > = 64 位,并且它必须支持 PKCS #7 填充的 CBC 模式加密。哈希算法的摘要大小必须为 > = 128 位,并且必须支持使用 BCRYPTALG处理HMAC标志标志打开。*提供程序属性可以设置为 null,以将默认提供程序用于指定的算法。有关详细信息,请参阅.aspx)文档。

若要使用 Galois/Counter 模式加密和验证来指定自定义 Windows CNG 算法,请创建包含算法信息的CngGcmAuthenticatedEncryptorConfiguration实例:

  1. services.AddDataProtection()
  2. .UseCustomCryptographicAlgorithms(
  3. new CngGcmAuthenticatedEncryptorConfiguration()
  4. {
  5. // Passed to BCryptOpenAlgorithmProvider
  6. EncryptionAlgorithm = "AES",
  7. EncryptionAlgorithmProvider = null,
  8. // Specified in bits
  9. });

若要使用 Galois/Counter 模式加密和验证来指定自定义 Windows CNG 算法,请创建包含算法信息的实例:

备注

对称块密码算法的密钥长度必须为 > = 128 位,块大小正好为128位,并且必须支持 GCM 加密。可以将EncryptionAlgorithmProvider属性设置为 null,以将默认提供程序用于指定的算法。有关详细信息,请参阅.aspx)文档。

尽管不是作为第一类 API 公开的,但数据保护系统的扩展能力足以允许指定几乎任何类型的算法。例如,可以保留硬件安全模块(HSM)中包含的所有密钥,并提供核心加密和解密例程的自定义实现。有关详细信息,请参阅核心加密扩展性中的 。

在 Docker 容器中托管时保持密钥Persisting keys when hosting in a Docker container

在容器中托管时,应在以下任一项中维护密钥:

  • 一个文件夹,它是在容器的生存期之外保留的 Docker 卷,如共享卷或主机装入的卷。
  • 外部提供程序,如Azure Key Vault或。

通过 Redis 保持密钥Persisting keys with Redis

只应使用支持的 Redis 版本来存储密钥。Azure Blob 存储是持久性的,可用于存储密钥。有关详细信息,请参阅。

其他资源Additional resources