【问题标题】:System.Security.Cryptography.CryptographicException: 'The key {00000000-0000-0000-0000-000000000000} was not found in the key ring.'System.Security.Cryptography.CryptographicException:“在密钥环中找不到密钥 {00000000-0000-0000-0000-000000000000}。”
【发布时间】:2017-06-12 19:49:04
【问题描述】:

我部署了一个 webjob (.Net 4.6),它会加密一些 url 字符串并通过电子邮件将其发送给客户。我使用 .NET Core 的 IDataProtector 进行加密,我不得不手动引用 DLL,因为 webjob .net 4.6 不支持它的库。

例如在 webjob 中:

IDataProtector protector = provider.CreateProtector("myProtector")
http://test.com/Email/Agreement?n=" + protector.Protect(name) + "&a=" + protector.Protect(address)

变成链接

http://test.com/Email/Agreement?n=CfDJ8AAAAAAAAAAAAAAAAAAAAAD96g09022UwEG-GyVftzkm-n2JuL1hmvL5HLyghXliIgJ_N014EBqBFfWjmdA&a=CfDJ8AAAAAAAAAAAAAAAAAAAAAALoq9IuMBZKozhzH3jRaHpyFE1wtXzQK3T_0RNuX9LsSVxPITWgU9ZR21jXLk3YGjt

在电子邮件中。

当客户点击他们电子邮件中的 url 链接时,它会转到我的客户端应用程序的 (.Net Core 1.1) 控制器来解密 url 字符串以弹出协议页。

例如:

public EmailController(IDataProtectionProvider provider)
{         
    _protector = provider.CreateProtector("myProtector");
}
public IActionResult Agreement(string n, string a)
{     
    var decryptName = _protector.Unprotect(n);
    var decryptAddress = _protector.Unprotect(a);
}

但是,当我尝试取消保护它们时,我收到以下错误消息:

System.Security.Cryptography.CryptographicException: '在密钥环中找不到密钥 {00000000-0000-0000-0000-000000000000}。'

当我搜索答案时,我意识到我可以配置数据保护以将密钥存储到 Azure Blob 存储。这个link 向我展示了如何将密钥持久保存到 azure blob 存储。

问题:

  1. 除了将密钥存储到 Azure Blob 存储之外,最好的方法是什么?
  2. 如果我在正确的轨道上,我该如何存储它?
  3. 如何为 webjob 项目配置与没有 Startup.cs 进行配置的链接中所示相同的设置?

非常感谢您的帮助。

【问题讨论】:

    标签: azure-webjobs data-protection azure-blob-storage asp.net-core-1.1 cryptographicexception


    【解决方案1】:

    除了将密钥存储到 azure blob 存储之外,最好的方法是什么?

    根据您提供的文档,我们可以将密钥存储在文件系统、Azure Redis、Azure 存储和注册表中。由于 Web Job(Azure Web App)不支持 Registry。如果选择文件系统,我们还需要在 Web Job 和您的 Web 应用程序之间传输密钥。所以 Azure Redis 和 Azure Storage 将是很好的方法。

    如果我在正确的轨道上,我该如何存储它?

    以下是如何在 Azure 存储上存储密钥的详细步骤。

    第 1 步,如果您没有 Azure 存储帐户,则需要创建一个。

    第 2 步,使用 NuGet 安装 Microsoft.AspNetCore.DataProtection.AzureStorage 包。

    第 3 步,使用以下代码配置 DataProtection。我们需要调用 SetApplicationName 方法并使用与您的 Web Job 相同的应用程序名称。

    var storageAccount = CloudStorageAccount.Parse("put your azure storage connection string here");
    var client = storageAccount.CreateCloudBlobClient();
    
    var container = client.GetContainerReference("key-container");
    container.CreateIfNotExistsAsync().GetAwaiter().GetResult();
    
    services.AddDataProtection().SetApplicationName("myapplication")
        .PersistKeysToAzureBlobStorage(container, "keys.xml");
    

    第 4 步,在您的控制器中,您可以使用 IDataProtectionProvider,如下所示。

    public class HomeController : Controller
    {
        private IDataProtector _protector;
        public HomeController(IDataProtectionProvider provider)
        {
            _protector = provider.CreateProtector("test-purpose");
        }
    
        public IActionResult Index()
        {
            string encryptedTExt = _protector.Protect("abcd");
            return Content(encryptedTExt);
        }
    }
    

    如何为 webjob 项目配置相同的设置,如链接中所示,其中没有用于配置的 Startup.cs?

    第 1 步,您需要添加对以下 DLL 的引用。

    第二步,添加 IDataProtector 的包装类,如下所示。

    public class EncryptService
    {
        IDataProtector _protector;
    
        // the 'provider' parameter is provided by DI
        public EncryptService(IDataProtectionProvider provider)
        {
            _protector = provider.CreateProtector("test-purpose");
        }
    
        public string Protect(string text)
        {
            return _protector.Protect(text);
        }
    
        public string Unprotect(string encryptedText)
        {
            return _protector.Unprotect(encryptedText);
        }
    }
    

    第 3 步,使用 ServiceCollection 配置数据保护服务。请注意,我们需要调用 SetApplicationName 方法并使用与您的 Web 应用程序相同的应用程序名称

    static void Main()
    {
        var storageAccount = CloudStorageAccount.Parse("put your azure storage connection string here");
        var client = storageAccount.CreateCloudBlobClient();
    
        var container = client.GetContainerReference("key-container");
        container.CreateIfNotExistsAsync().GetAwaiter().GetResult();
    
        var serviceCollection = new ServiceCollection();
    
        serviceCollection.AddDataProtection().SetApplicationName("myapplication")
            .PersistKeysToAzureBlobStorage(container, "keys.xml"); 
    
        var services = serviceCollection.BuildServiceProvider();
    }
    

    第 4 步,之后,您可以使用以下代码来加密或解密您的数据。

    var encryptService = ActivatorUtilities.CreateInstance<EncryptService>(services);
    string text = encryptService.Protect("abcd");
    

    【讨论】:

    • 如果您将预先存在的名为 keys.xml 的密钥添加到 blob 存储中,我认为这些密钥将被读取而不会创建新密钥?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-07
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多