System.Security.Cryptography.CryptographicException: "Ключ {00000000-0000-0000-0000-000000000000} не был найден в кольце для ключей."

Я развернул веб-задание (.Net 4.6), которое шифрует некоторые строки URL-адресов и отправляет их клиентам по электронной почте. Я использовал IDataProtector.NET Core для шифрования, и мне пришлось вручную ссылаться на 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} не был найден в кольце для ключей."

Когда я искал ответ, я понял, что могу настроить защиту данных для хранения ключей в хранилище BLOB-объектов Azure. Эта ссылка показывает, как сохранить ключи в хранилище BLOB-объектов Azure.

Вопросы:

  1. Как лучше всего хранить ключи от хранилища BLOB-объектов Azure?
  2. Если я на правильном пути, как мне его сохранить?
  3. Как настроить тот же параметр для проекта webjob, который показан в ссылке, в которой нет файла Startup.cs для настройки?

Помощь очень ценится.

1 ответ

Решение

Как лучше всего хранить ключи от хранилища BLOB-объектов Azure?

На основании предоставленного вами документа мы можем хранить ключ в файловой системе, Azure Redis, хранилище Azure и реестре. Поскольку реестр не поддерживается веб-заданием (Azure Web App). При выборе файловой системы нам также необходимо передать ключи между веб-заданием и вашим веб-приложением. Так что Azure Redis и Azure Storage будут хорошими подходами.

Если я на правильном пути, как мне его сохранить?

Ниже приведены подробные инструкции по хранению ключей в хранилище Azure.

Шаг 1, вам нужно создать учетную запись хранилища Azure, если у вас ее нет.

Шаг 2, установите пакет Microsoft.AspNetCore.DataProtection.AzureStorage с помощью NuGet.

Шаг 3, настройте DataProtection, используя следующий код. Нам нужно вызвать метод SetApplicationName и использовать то же имя приложения, что и ваше веб-задание.

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.

введите описание изображения здесь

Шаг 2. Добавьте класс-оболочку 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 и использовать то же имя приложения, что и ваше веб-приложение.

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