System.Security.Cryptography.CryptographicException: 'The key {00000000-0000-0000-0000-000000000000} was not found in the key ring.'

System.Security.Cryptography.CryptographicException: 'The key {00000000-0000-0000-0000-000000000000} was not found in the key ring.'

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

例如在网络作业中:

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

变成了 link

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

在电子邮件中。

当客户在他们的电子邮件中单击 url link 时,它将转到我的 客户端应用程序 的(.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: 'The key {00000000-0000-0000-0000-000000000000} was not found in the key ring.'

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

问题:

  1. 除了将密钥存储到 Azure Blob 存储之外,最好的方法是什么?
  2. 如果我走对了,我该如何存储?
  3. 如何为没有 Startup.cs 配置的 link 中所示的 webjob 项目配置相同的设置?

非常感谢您的帮助。

What is the best approach other than storing a key to azure blob storage?

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

If I am on the right track, how do I store it?

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

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

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

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

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

How do I configure the same setting for the webjob project as shown in the link which does not have Startup.cs for configuration?

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

第 2 步,添加 IDataProtector 的包装器 class,如下所示。

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

第三步,使用ServiceCollection配置Data Protection服务。请注意,我们需要调用 SetApplicationName 方法并使用与您的网络应用程序相同的应用程序名称

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