使用 ASP.NET Core 在 Windows 和 Azure 中实现密钥静态加密

数据保护系统默认采用发现机制来确定加密密钥的静态加密方式。 开发人员可以替代发现机制并手动指定密钥的静态加密方式。

警告

如果指定显式密钥保存位置,数据保护系统将注销默认密钥静态加密机制。 因此,不再对密钥进行静态加密。 建议为生产部署指定显式密钥加密机制。 本主题介绍了静态加密机制选项。

Azure Key Vault

若要将密钥存储在 Azure Key Vault 中,请使用 Startup 类中的 ProtectKeysWithAzureKeyVault 来配置系统。

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToAzureBlobStorage(new Uri("<blobUriWithSasToken>"))
        .ProtectKeysWithAzureKeyVault("<keyIdentifier>", "<clientId>", "<clientSecret>");
}

有关详细信息,请参阅配置 ASP.NET Core 数据保护:ProtectKeysWithAzureKeyVault

Windows DPAPI

仅适用于 Windows 部署。

使用 Windows DPAPI 时,系统会在将密钥材料保存到存储之前使用 CryptProtectData 进行加密。 DPAPI 加密机制适用于从未在当前计算机之外读取的数据(尽管可将这些密钥备份到 Active Directory)。 若要配置 DPAPI 密钥静态加密,请调用 ProtectKeysWithDpapi 扩展方法之一:

public void ConfigureServices(IServiceCollection services)
{
    // Only the local user account can decrypt the keys
    services.AddDataProtection()
        .ProtectKeysWithDpapi();
}

如果在没有参数的情况下调用 ProtectKeysWithDpapi,则只有当前 Windows 用户帐户才能解密保存的密钥环。 你可以选择指定计算机上的任何用户帐户(不仅仅是当前用户帐户)都能解密密钥环:

public void ConfigureServices(IServiceCollection services)
{
    // All user accounts on the machine can decrypt the keys
    services.AddDataProtection()
        .ProtectKeysWithDpapi(protectToLocalMachine: true);
}

X.509 证书

如果应用分布在多台计算机上,那么在计算机上分发共享 X.509 证书并将托管应用配置为使用该证书实现密钥静态加密可能会很方便:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .ProtectKeysWithCertificate("3BCE558E2AD3E0E34A7743EAB5AEA2A9BD2575A0");
}

由于 .NET Framework 限制,仅支持具有 CAPI 私钥的证书。 有关这些限制可能的解决方法,请参阅以下内容。

Windows DPAPI-NG

此机制仅适用于 Windows 8/Windows Server 2012 或更高版本。

从 Windows 8 开始,Windows 操作系统支持 DPAPI-NG(也称为 CNG DPAPI)。 有关详细信息,请参阅关于 CNG DPAPI

主体编码为保护描述符规则。 在以下调用 ProtectKeysWithDpapiNG 的示例中,只有具有指定 SID 的已加入域的用户才能解密密钥环:

public void ConfigureServices(IServiceCollection services)
{
    // Uses the descriptor rule "SID=S-1-5-21-..."
    services.AddDataProtection()
        .ProtectKeysWithDpapiNG("SID=S-1-5-21-...",
        flags: DpapiNGProtectionDescriptorFlags.None);
}

还有一个 ProtectKeysWithDpapiNG 的无参数重载。 可使用此便捷方法指定规则“SID={CURRENT_ACCOUNT_SID}”,其中 CURRENT_ACCOUNT_SID 是当前 Windows 用户帐户的 SID:

public void ConfigureServices(IServiceCollection services)
{
    // Use the descriptor rule "SID={current account SID}"
    services.AddDataProtection()
        .ProtectKeysWithDpapiNG();
}

在此方案中,AD 域控制器负责分发 DPAPI-NG 操作使用的加密密钥。 目标用户可以从任何已加入域的计算机解密已加密的有效负载(前提是该进程在其标识下运行)。

使用 Windows DPAPI-NG 进行基于证书的加密

如果应用在 Windows 8.1/Windows Server 2012 R2 或更高版本上运行,你可以使用 Windows DPAPI-NG 执行基于证书的加密。 使用规则描述符字符串“CERTIFICATE=HashId:THUMBPRINT”,其中 THUMBPRINT 是证书的十六进制编码 SHA1 指纹:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .ProtectKeysWithDpapiNG("CERTIFICATE=HashId:3BCE558E2...B5AEA2A9BD2575A0",
            flags: DpapiNGProtectionDescriptorFlags.None);
}

指向此存储库的任何应用都必须在 Windows 8.1/Windows Server 2012 R2 或更高版本上运行才能解密密钥。

自定义密钥加密

如果内置机制不适用,开发人员可以通过提供自定义 IXmlEncryptor 来指定自己的密钥加密机制。