- 配置 ASP.NET Core 数据保护Configure ASP.NET Core Data Protection
- ProtectKeysWithAzureKeyVaultProtectKeysWithAzureKeyVault
- PersistKeysToFileSystemPersistKeysToFileSystem
- ProtectKeysWithProtectKeysWith
- UnprotectKeysWithAnyCertificateUnprotectKeysWithAnyCertificate
- SetDefaultKeyLifetimeSetDefaultKeyLifetime
- SetApplicationNameSetApplicationName
- DisableAutomaticKeyGenerationDisableAutomaticKeyGeneration
- 每应用程序隔离Per-application isolation
- 用 UseCryptographicAlgorithms 更改算法Changing algorithms with UseCryptographicAlgorithms
- 在 Docker 容器中托管时保持密钥Persisting keys when hosting in a Docker container
- 通过 Redis 保持密钥Persisting keys with Redis
- 其他资源Additional resources
配置 ASP.NET Core 数据保护Configure ASP.NET Core Data Protection
本文内容
当数据保护系统已初始化时,它将基于操作环境应用默认设置。这些设置通常适用于在一台计算机上运行的应用程序。在某些情况下,开发人员可能想要更改默认设置:
- 应用程序分布在多台计算机上。
- 出于合规性原因。
在这些情况下,数据保护系统提供了丰富的配置 API。
警告
与配置文件类似,应使用适当的权限保护数据保护密钥环。你可以选择对静态密钥加密,但这不会阻止攻击者创建新密钥。因此,应用的安全将受到影响。使用数据保护配置的存储位置应该将其访问权限限制为应用本身,这与保护配置文件的方式类似。例如,如果选择将密钥环存储在磁盘上,请使用文件系统权限。确保你的 web 应用在其下运行的标识具有对该目录的读取、写入和创建访问权限。如果使用 Azure Blob 存储,则只有 web 应用应能够在 Blob 存储中读取、写入或创建新条目等。
扩展方法AddDataProtection返回IDataProtectionBuilder。IDataProtectionBuilder
公开扩展方法,你可以将这些方法链接在一起来配置数据保护选项。
本文中使用的数据保护扩展插件需要以下 NuGet 包:
ProtectKeysWithAzureKeyVaultProtectKeysWithAzureKeyVault
若要在Azure Key Vault中存储密钥,请在 Startup
类中配置ProtectKeysWithAzureKeyVault的系统:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("<blobUriWithSasToken>"))
.ProtectKeysWithAzureKeyVault("<keyIdentifier>", "<clientId>", "<clientSecret>");
}
设置密钥环存储位置(例如, PersistKeysToAzureBlobStorage)。必须设置位置,因为调用 ProtectKeysWithAzureKeyVault
实现了禁用自动数据保护设置的IXmlEncryptor ,包括密钥环存储位置。前面的示例使用 Azure Blob 存储来持久保存密钥环。有关详细信息,请参阅密钥存储提供程序: Azure 存储。还可以通过PersistKeysToFileSystem将密钥环保存到本地。
keyIdentifier
是用于密钥加密的密钥保管库密钥标识符。例如,在 contosokeyvault
中名为 dataprotection
的密钥保管库中创建的密钥具有密钥标识符 https://contosokeyvault.vault.azure.net/keys/dataprotection/
。向应用提供对密钥保管库的解包密钥和包装密钥权限。
ProtectKeysWithAzureKeyVault
重载:
- ProtectKeysWithAzureKeyVault (IDataProtectionBuilder,KeyVaultClient,String)允许使用KeyVaultClient使数据保护系统能够使用密钥保管库。
- ProtectKeysWithAzureKeyVault (IDataProtectionBuilder,string,string,X509Certificate2)允许使用
ClientId
和X509Certificate使数据保护系统能够使用密钥保管库。 - ProtectKeysWithAzureKeyVault (IDataProtectionBuilder,string,string,string)允许使用
ClientId
和ClientSecret
使数据保护系统能够使用密钥保管库。
PersistKeysToFileSystemPersistKeysToFileSystem
若要将密钥存储在 UNC 共享上,而不是存储在 % LOCALAPPDATA% 默认位置,请使用PersistKeysToFileSystem配置系统:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
}
警告
如果更改密钥持久性位置,系统将不再自动加密静态密钥,因为它不知道 DPAPI 是否为适当的加密机制。
ProtectKeysWithProtectKeysWith
可以通过调用ProtectKeysWith*配置 api,将系统配置为保护静态密钥。请考虑以下示例,该示例将密钥存储在 UNC 共享上,并使用特定的 x.509 证书对静态密钥进行加密:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate("thumbprint");
}
在 ASP.NET Core 2.1 或更高版本中,你可以提供ProtectKeysWithCertificate的X509Certificate2 ,例如从文件中加载的证书:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", "password"));
}
有关内置密钥加密机制的更多示例和讨论,请参阅静态密钥加密。
UnprotectKeysWithAnyCertificateUnprotectKeysWithAnyCertificate
在 ASP.NET Core 2.1 或更高版本中,你可以使用UnprotectKeysWithAnyCertificate的X509Certificate2
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", "password"));
.UnprotectKeysWithAnyCertificate(
new X509Certificate2("certificate_old_1.pfx", "password_1"),
new X509Certificate2("certificate_old_2.pfx", "password_2"));
}
SetDefaultKeyLifetimeSetDefaultKeyLifetime
若要将系统配置为使用14天的密钥生存期而不是默认的90天,请使用SetDefaultKeyLifetime:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}
SetApplicationNameSetApplicationName
默认情况下,数据保护系统基于其内容根路径将应用彼此隔离,即使它们共享相同的物理密钥存储库。这可防止应用了解彼此的受保护负载。
在应用之间共享受保护的负载:
- 用相同的值在每个应用中配置 SetApplicationName。
- 在应用程序中使用相同版本的数据保护 API 堆栈。在应用的项目文件中执行以下任一操作:
- 通过AspNetCore 元包引用相同的共享框架版本。
- 引用相同的数据保护包版本。
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetApplicationName("shared app name");
}
DisableAutomaticKeyGenerationDisableAutomaticKeyGeneration
您可能会遇到这样的情况:不希望应用程序在接近过期时自动滚动更新密钥(创建新的密钥)。这种情况的一个示例可能是在主/辅助关系中设置的应用,其中只有主应用负责密钥管理问题,辅助应用只是具有密钥环的只读视图。可以通过使用 DisableAutomaticKeyGeneration配置系统,将辅助应用配置为将密钥环视为只读:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.DisableAutomaticKeyGeneration();
}
每应用程序隔离Per-application isolation
数据保护系统提供了 ASP.NET Core 主机,但它自动隔离了从另一个,应用程序,即使这些应用在相同的工作进程帐户下运行,并且使用相同的主密钥材料。这有点类似于 IsolateApps 的 <machineKey>
元素中的修饰符。
隔离机制的工作原理是将本地计算机上的每个应用视为唯一的租户,因此,任何给定应用的根 IDataProtector 会自动将应用 ID 包含为鉴别器。应用的唯一 ID 是应用的物理路径:
- 对于在 IIS 中托管的应用,唯一 ID 是应用的 IIS 物理路径。如果在 web 场环境中部署了应用,则此值是稳定的,假定在 web 场中的所有计算机上配置了类似的 IIS 环境。
- 对于在Kestrel 服务器上运行的自承载应用程序,唯一 ID 是指向磁盘上的应用程序的物理路径。
唯一标识符的设计目的是在每个应用程序和计算机本身—重置。
此隔离机制假定应用不是恶意的。恶意应用始终会影响在同一工作进程帐户下运行的任何其他应用。在应用不受信任的共享主机环境中,托管提供商应采取措施来确保应用之间的操作系统级隔离,包括分离应用程序的底层密钥存储库。
如果数据保护系统不是由 ASP.NET Core 主机提供的(例如,如果通过 DataProtectionProvider
具体类型对其进行实例化),则默认情况下禁用应用程序隔离。禁用应用隔离后,只要提供相应的用途,同一密钥材料支持的所有应用就可以共享有效负载。若要在此环境中提供应用隔离,请对配置对象调用SetApplicationName方法,并为每个应用提供唯一的名称。
用 UseCryptographicAlgorithms 更改算法Changing algorithms with UseCryptographicAlgorithms
数据保护堆栈允许您更改新生成的密钥使用的默认算法。执行此操作的最简单方法是从配置回调调用UseCryptographicAlgorithms :
services.AddDataProtection()
.UseCryptographicAlgorithms(
new AuthenticatedEncryptorConfiguration()
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
services.AddDataProtection()
.UseCryptographicAlgorithms(
new AuthenticatedEncryptionSettings()
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
默认 EncryptionAlgorithm 为 AES-256-CBC,默认 ValidationAlgorithm 为 HMACSHA256。系统管理员可以通过计算机范围的策略设置默认策略,但对 UseCryptographicAlgorithms
的显式调用会替代默认策略。
通过调用 UseCryptographicAlgorithms
,可以从预定义的内置列表中指定所需的算法。您无需担心算法的实现。在上述方案中,如果在 Windows 上运行,数据保护系统将尝试使用 AES 的 CNG 实现。否则,它会回退到托管的系统。
可以通过调用UseCustomCryptographicAlgorithms手动指定实现。
提示
更改算法不会影响密钥环中的现有密钥。它仅影响新生成的键。
指定自定义托管算法Specifying custom managed algorithms
若要指定自定义托管算法,请创建一个指向实现类型的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)
});
若要指定自定义托管算法,请创建一个指向实现类型的ManagedAuthenticatedEncryptionSettings实例:
serviceCollection.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new ManagedAuthenticatedEncryptionSettings()
{
// A type that subclasses SymmetricAlgorithm
EncryptionAlgorithmType = typeof(Aes),
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// A type that subclasses KeyedHashAlgorithm
ValidationAlgorithmType = typeof(HMACSHA256)
});
通常,*类型属性必须指向system.security.cryptography.symmetricalgorithm和KeyedHashAlgorithm的具体实例实例(通过公共无参数的 ctor)实现,尽管系统特别适用于一些值(如 typeof(Aes)
)以方便使用。
备注
System.security.cryptography.symmetricalgorithm 必须具有≥128位的密钥长度和≥64位的块大小,并且必须支持 PKCS #7 填充的 CBC 模式加密。KeyedHashAlgorithm 的摘要大小必须为 > = 128 位,并且它必须支持长度等于哈希算法摘要长度的键。KeyedHashAlgorithm 不一定是 HMAC。
指定自定义 Windows CNG 算法Specifying custom Windows CNG algorithms
若要通过 HMAC 验证使用 CBC 模式加密指定自定义 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
});
若要通过 HMAC 验证使用 CBC 模式加密指定自定义 Windows CNG 算法,请创建包含算法信息的CngCbcAuthenticatedEncryptionSettings实例:
services.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new CngCbcAuthenticatedEncryptionSettings()
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// Passed to BCryptOpenAlgorithmProvider
HashAlgorithm = "SHA256",
HashAlgorithmProvider = null
});
备注
对称块加密算法的密钥长度必须为 > = 128 位,块大小为 > = 64 位,并且它必须支持 PKCS #7 填充的 CBC 模式加密。哈希算法的摘要大小必须为 > = 128 位,并且必须支持使用 BCRYPTALG处理HMAC标志标志打开。*提供程序属性可以设置为 null,以将默认提供程序用于指定的算法。有关详细信息,请参阅BCryptOpenAlgorithmProvider.aspx)文档。
若要使用 Galois/Counter 模式加密和验证来指定自定义 Windows CNG 算法,请创建包含算法信息的CngGcmAuthenticatedEncryptorConfiguration实例:
services.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new CngGcmAuthenticatedEncryptorConfiguration()
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256
});
若要使用 Galois/Counter 模式加密和验证来指定自定义 Windows CNG 算法,请创建包含算法信息的CngGcmAuthenticatedEncryptionSettings实例:
services.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new CngGcmAuthenticatedEncryptionSettings()
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256
});
备注
对称块密码算法的密钥长度必须为 > = 128 位,块大小正好为128位,并且必须支持 GCM 加密。可以将EncryptionAlgorithmProvider属性设置为 null,以将默认提供程序用于指定的算法。有关详细信息,请参阅BCryptOpenAlgorithmProvider.aspx)文档。
指定其他自定义算法Specifying other custom algorithms
尽管不是作为第一类 API 公开的,但数据保护系统的扩展能力足以允许指定几乎任何类型的算法。例如,可以保留硬件安全模块(HSM)中包含的所有密钥,并提供核心加密和解密例程的自定义实现。有关详细信息,请参阅核心加密扩展性中的IAuthenticatedEncryptor 。
在 Docker 容器中托管时保持密钥Persisting keys when hosting in a Docker container
在Docker容器中托管时,应在以下任一项中维护密钥:
- 一个文件夹,它是在容器的生存期之外保留的 Docker 卷,如共享卷或主机装入的卷。
- 外部提供程序,如Azure Key Vault或Redis。
通过 Redis 保持密钥Persisting keys with Redis
只应使用支持Redis 数据暂留的 Redis 版本来存储密钥。Azure Blob 存储是持久性的,可用于存储密钥。有关详细信息,请参阅此 GitHub 问题。