配置 ASP.NET Core数据保护

当数据保护系统已初始化时,它将基于操作环境应用默认设置 这些设置通常适用于在一台计算机上运行的应用程序。 在某些情况下,开发人员可能想要更改默认设置:

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

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

警告

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

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

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

ProtectKeysWithAzureKeyVault

若要在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 重载:

PersistKeysToFileSystem

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

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

警告

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

ProtectKeysWith*

可以通过调用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 或更高版本中,你可以提供ProtectKeysWithCertificateX509Certificate2 ,例如从文件中加载的证书:

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

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

UnprotectKeysWithAnyCertificate

在 ASP.NET Core 2.1 或更高版本中,你可以使用UnprotectKeysWithAnyCertificateX509Certificate2

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"));
}

SetDefaultKeyLifetime

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

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

SetApplicationName

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

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

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

DisableAutomaticKeyGeneration

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

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

每应用程序隔离

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

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

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

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

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

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

用 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手动指定实现。

提示

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

指定自定义托管算法

若要指定自定义托管算法,请创建一个指向实现类型的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.symmetricalgorithmKeyedHashAlgorithm的具体实例实例(通过公共无参数的 ctor)实现,尽管系统特别适用于一些值(如 typeof(Aes))以方便使用。

备注

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

指定自定义 Windows CNG 算法

若要通过 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 位,并且必须支持使用 BCRYPT_ALG_处理_HMAC_标志标志打开。 *提供程序属性可以设置为 null,以将默认提供程序用于指定的算法。 有关详细信息,请参阅BCryptOpenAlgorithmProvider文档。

若要使用 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文档。

指定其他自定义算法

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

在 Docker 容器中托管时保持密钥

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

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

通过 Redis 保持密钥

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

其他资源

上一篇:ASP.NET Core 中的数据保护配置

下一篇:数据保护密钥管理和 ASP.NET Core 中的生存期

关注微信小程序
程序员编程王-随时随地学编程

扫描二维码
程序员编程王

扫一扫关注最新编程教程