ASP.NET Core 2.1 中的数据保护仅适用于一台机器

Posted

技术标签:

【中文标题】ASP.NET Core 2.1 中的数据保护仅适用于一台机器【英文标题】:Data protection in ASP.NET Core 2.1 only works on one machine 【发布时间】:2018-11-23 10:01:48 【问题描述】:

我正在使用ASP.NET Core Data Protection system 使用应用程序 A 加密数据并使用应用程序 B 解密它。

在开发机器上运行时,加密和解密都可以工作,但是当应用程序 B 移动到生产机器上时,它不再能够解密,因为 IDataProtector.Unprotect 方法会引发异常:

System.InvalidOperationException:密钥环不包含 有效的默认保护密钥。数据保护系统无法创建 一个新的密钥,因为密钥的自动生成被禁用。

这是我用来在应用程序 B 中配置解密的代码:

sKeysPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Keys");

services.AddDataProtection()
    .SetApplicationName("My Application") // Application A sets this same name
    .PersistKeysToFileSystem(new DirectoryInfo(sKeysPath))
    .ProtectKeysWithCertificate("634D3F23...")
    //.ProtectKeysWithCertificate(x509Certificate2) // I've tried using an X509 certificate parameter but it gives the same result as providing the thumbprint of the one in the certificate store
    .DisableAutomaticKeyGeneration(); // Application A is the master key generator so do not generate keys

生产机器确实包含相同的密钥文件夹(带有 .pfx 和 .xml 文件)和安装在 Windows 证书存储中的相同密钥。

据我了解,通过向数据保护系统提供证书文件,它应该可以在任何机器上运行,而不是绑定到特定机器或 Windows 用户。这个假设是不正确的,还是我执行解密的方式有问题?

以下是一些更详细的日志记录消息:

2018-06-13 16:32:32.6750 | TRACE | Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector | 5 | Performing unprotect operation to key 846541... with purposes ('My Application', 'My Purpose').

2018-06-13 16:32:32.6750 | DEBUG | Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository | 37 | Reading data from file 'C:\inetpub\wwwroot\My Website\Keys\key-846541....xml'.

2018-06-13 16:32:32.6750 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager | 18 | Found key 846541....

2018-06-13 16:32:32.6750 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver | 13 | Considering key 846541... with expiration date 2038-01-18 20:54:13Z as default key.

2018-06-13 16:32:32.6750 | DEBUG | Microsoft.AspNetCore.DataProtection.TypeForwardingActivator | Forwarded activator type request from Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor, Microsoft.AspNetCore.DataProtection, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60

2018-06-13 16:32:32.7051 | ERROR | Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager | 24 | An exception occurred while processing the key element '<key id="846541..." version="1" />'. Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset does not exist

2018-06-13 16:32:32.7051 | TRACE | Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager | 25 | An exception occurred while processing the key element '<key id="846541..." version="1" />...

2018-06-13 16:32:32.7051 | WARN | Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver | 12 | Key 846541... is ineligible to be the default key because its CreateEncryptor method failed. Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset does not exist

2018-06-13 16:32:32.7051 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver | 14 | Key 846541... is no longer under consideration as default key because it is expired, revoked, or cannot be deciphered.

2018-06-13 16:32:32.7051 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver | 53 | Repository contains no viable default key. Caller should generate a key with immediate activation.

2018-06-13 16:32:32.7051 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider | 57 | Policy resolution states that a new key should be added to the key ring.

2018-06-13 16:32:32.7051 | ERROR | Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider | 49 | The key ring does not contain a valid default key, and the key manager is configured with auto-generation of keys disabled.

2018-06-13 16:32:32.7051 | ERROR | Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider | 48 | An error occurred while reading the key ring. System.InvalidOperationException: The key ring does not contain a valid default protection key. The data protection system cannot create a new key because auto-generation of keys is disabled.

【问题讨论】:

两台机器的系统时间是否同步?查看DefaultKeyResolver 的源代码,逻辑看起来对时间很敏感,如果系统时钟不同步,可能无法找到有效的默认密钥 是的,它们是同步的。 两台机器如何共享密钥?它们是否共享一个通用的文件系统驱动器?即当机器A在磁盘上的xml文件中的环上创建一个新密钥时,机器B如何知道新密钥? 您是否尝试过将日志级别设置为调试或跟踪,查看他们在考虑并排除默认键候选时记录的代码 您是否尝试过将xml文件再次复制到机器B。 【参考方案1】:

感谢 Joe Audette 的建议,我检查了详细的日志记录并发现了一个更具体的错误,该错误将我指向 this answer,它有解决方案。

问题是 Windows 证书存储中证书的权限没有设置 IIS_IUSRS 组以允许读取访问(右键单击证书 → 所有任务 → 管理私钥...)。这个问题没有出现在开发机器上,因为它是在 Visual Studio 的用户上下文中运行的。

【讨论】:

你好。我也有同样的问题,但是权限没有解决。您是如何启用此详细日志的? Tks 您可以在 DataProtectionProvider.Create 中传递选项并执行 options.Services.AddLogging(configure => configure.SetMinimumLevel(LogLevel.Trace).AddConsole()); 太棒了!设置权限也对我有帮助。非常感谢! ? 在另一种情况下,我收到了与 OP 相同的错误消息,这实际上是因为我(故意)确实调用了 DisableAutomaticKeyGeneration()。删除呼叫后,错误消失了。【参考方案2】:

我遇到了类似的问题,但它是在尝试共享相同 cookie 的两个不同 ASP.NET Core 应用程序之间。 Microsoft.AspNetCore.Authentication.Cookies(2.1.2 与 2.2.0)中的次要版本不匹配导致其中一个应用程序无法找到另一个版本创建的密钥。

在此处添加此答案(即使它没有回答上述问题),因为错误消息完全匹配,并且希望它可以为某人节省几个小时。

【讨论】:

【参考方案3】:

我在 2.2 应用程序中也遇到了类似的问题,因为证书是自签名的。目前我已经通过实现我自己的CertificateResolver 类和ProtectKeysWithCertificate 方法来避开它,它们不验证证书。然而,对我来说真正的解决方案是使用有效的证书。

为遇到此问题的任何人提供一些额外信息。

【讨论】:

以上是关于ASP.NET Core 2.1 中的数据保护仅适用于一台机器的主要内容,如果未能解决你的问题,请参考以下文章

使用用户名和密码 Asp Net Core 2.1 保护 swagger 文档页面

ASP.NET Core 2.1对GDPR的支持

Asp.Net Core Data Protection API 用于保护数据库中的数据

如何仅为 ASP.NET 5 (ASP.NET Core) 中的受保护操作添加令牌验证

如何在 ASP.NET Core 2.1 中的计时器上运行 BackgroundService

在 ASP.NET Core 2.1 Web 客户端中存储不记名令牌的位置