Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
При инициализации системы защиты данных она применяет параметры по умолчанию в зависимости от операционной среды. Эти параметры подходят для приложений, работающих на одном компьютере. Однако есть случаи, когда разработчику может потребоваться изменить параметры по умолчанию:
- Приложение распространяется на несколько компьютеров.
- По соображениям соответствия требованиям.
В этих сценариях система защиты данных предлагает широкий API конфигурации.
Warning
Как и в файлах конфигурации, кольцо ключей защиты данных должно быть защищено с помощью соответствующих разрешений. Вы можете зашифровать неактивные ключи, но это не предотвращает создание новых ключей злоумышленниками. Следовательно, это влияет на безопасность вашего приложения. Местоположение хранилища, настроенного с Data Protection, должно иметь доступ ограниченный только для самого приложения, аналогично тому, как защищаются файлы конфигурации. Например, если вы решили сохранить кольцо ключей на диске, используйте разрешения файловой системы. Убедитесь, что только учетная запись, под которой выполняется ваше веб-приложение, имеет права на чтение, запись и создание в этом каталоге. При использовании Хранилище BLOB-объектов Azure только веб-приложение должно иметь возможность читать, записывать или создавать новые записи в хранилище BLOB-объектов и т. д.
Метод расширения AddDataProtection возвращает IDataProtectionBuilder.
IDataProtectionBuilder
предоставляет методы расширения, которые можно объединить для настройки параметров защиты данных.
Note
Эта статья была написана для приложения, работающего в контейнере Docker. В контейнере Docker приложение всегда имеет одинаковый путь и, следовательно, тот же дискриминатор приложения. Приложения, которые должны выполняться в нескольких средах (например, локальные и развернутые), должны задать дискриминатор приложений по умолчанию для среды. Запуск приложения в нескольких средах выходит за рамки этой статьи.
Для расширений защиты данных, используемых в этой статье, требуются следующие пакеты NuGet:
Защита ключей с помощью Azure Key Vault (ProtectKeysWithAzureKeyVault
)
Чтобы взаимодействовать с Azure Key Vault локально с помощью учетных данных разработчика, войдите в учетную запись хранения в Visual Studio или войдите в Azure CLI. Если вы еще не установили Azure CLI, см. инструкции по установке Azure CLI. Следующую команду можно выполнить на панели PowerShell разработчика в Visual Studio или из командной оболочки, если не использовать Visual Studio:
az login
Дополнительные сведения см. в статье "Вход в Azure с помощью средств разработчика".
При создании хранилища ключей в портале Entra или Azure:
Настройте хранилище ключей для использования управления доступом на основе ролей Azure (RABC). Если вы не работаете в виртуальной сети Azure, в том числе для локальной разработки и тестирования, убедитесь, что общедоступный доступ на шаге "Сеть " включен (установлен). Включение общедоступного доступа предоставляет только конечную точку хранилища ключей. Учетные записи, прошедшие проверку подлинности, по-прежнему необходимы для доступа.
Создайте управляемую Identity Azure роль (или добавьте роль в существующий управляемый Identity объект, который планируется использовать) с ролью пользователя шифрования Key Vault . Назначьте управляемую Identity учетную запись службе приложений Azure, который размещает развертывание: Параметры>Identity>Назначено пользователем>Добавить.
Note
Если вы также планируете локально запустить приложение с авторизованным пользователем для доступа к объектам Blob с помощью Azure CLI или проверки подлинности службы Azure в Visual Studio, добавьте учетную запись разработчика пользователя Azure в службе управления доступом (IAM) с ролью Key Vault Crypto User. Если вы хотите использовать Azure CLI через Visual Studio, выполните
az login
команду на панели PowerShell разработчика и следуйте инструкциям по проверке подлинности с помощью клиента.Если шифрование ключей активно, ключи в файле ключей включают комментарий "This key is encrypted with Azure Key Vault." После запуска приложения выберите команду View/edit в контекстном меню в конце строки ключа, чтобы убедиться, что ключ присутствует с примененной безопасностью хранилища ключей.
При необходимости можно включить автоматическую ротацию ключей в Key Vault без необходимости беспокоиться о расшифровке данных с использованием ключей защиты данных, основанных на истекших или обновленных ключах. Каждый созданный ключ защиты данных содержит ссылку на ключ хранилища ключей, используемый для шифрования. Просто убедитесь, что вы сохранили ключи хранилища ключей с истекшим сроком действия, не удаляйте их в хранилище ключей. Кроме того, используйте идентификатор ключа без версии в конфигурации хранилища ключей приложения, где в конце идентификатора (например,
https://contoso.vault.azure.net/keys/data-protection
) не помещается GUID ключа. Используйте аналогичный срок действия для обоих ключей, при этом ключ хранилища обновляется чаще, чем ключ защиты данных, чтобы гарантировать использование нового ключа хранилища во время обновления ключа защиты данных.
Защита ключей с помощью Azure Key Vault реализует IXmlEncryptor, который отключает параметры автоматической защиты данных, включая местоположение хранилища для кольца ключей. Чтобы настроить поставщик хранилища BLOB-объектов Azure для хранения ключей в хранилище BLOB-объектов, следуйте указаниям поставщиков хранилища ключей в ASP.NET Core и вызовите одну из PersistKeysToAzureBlobStorage перегрузок в приложении. В следующем примере используется перегрузка, принимающая URI блоба и токен аутентификационных данных (TokenCredential), с использованием управляемого идентификатора Azure для контроля доступа на основе ролей (RBAC).
Чтобы настроить провайдера Azure Key Vault, вызовите одну из перегрузок ProtectKeysWithAzureKeyVault. В следующем примере используется перегрузка, которая принимает идентификатор ключа и учетные данные токена (TokenCredential), полагаясь на управляемый Identity для RBAC в производстве (ManagedIdentityCredential) или DefaultAzureCredential во время разработки и тестирования. Другие перегрузки принимают клиента хранилища ключей или идентификатор клиента приложения с секретным ключом клиента. Дополнительные сведения см. в статье Поставщики хранилища ключей в ASP.NET Core.
Дополнительные сведения об API и проверке подлинности пакета SDK Azure см. в статье Аутентификация приложений .NET в службах Azure с помощью библиотеки Azure Identity и предоставление доступа к ключам Key Vault, сертификатам и секретам с помощью управления доступом на основе ролей Azure. Инструкции по ведению журнала см. в статье "Ведение журнала с помощью пакета SDK Azure для .NET: ведение журнала без регистрации клиента". Для приложений, использующих внедрение зависимостей, приложение может вызывать AddAzureClientsCore, передавая true
для enableLogForwarding
, чтобы создать и настроить логирующую инфраструктуру.
Program
В файле, где зарегистрированы службы:
TokenCredential? credential;
if (builder.Environment.IsProduction())
{
credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
// Local development and testing only
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = "{TENANT ID}",
SharedTokenCacheTenantId = "{TENANT ID}"
};
credential = new DefaultAzureCredential(options);
}
builder.Services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
{MANAGED IDENTITY CLIENT ID}
: идентификатор управляемого Identity клиента Azure (GUID).
{TENANT ID}
: идентификатор клиента.
{APPLICATION NAME}
: SetApplicationName задает уникальное имя этого приложения в системе защиты данных. Значение должно совпадать между развертываниями приложения.
{BLOB URI}
: полный универсальный код ресурса (URI) к файлу ключа. Код URI создается службой хранилища Azure при создании файла ключа. Не используйте SAS.
{KEY IDENTIFIER}
: идентификатор ключа Azure Key Vault, используемый для шифрования ключей. Политика доступа позволяет приложению получать доступ к хранилищу ключей с разрешениями Get
, Unwrap Key
и Wrap Key
. Версия ключа получается из ключа на портале Entra или Azure после его создания. Если включить автоматическое вращение ключа хранилища, убедитесь, что в конфигурации хранилища ключей приложения используется идентификатор ключа без версии, где в конце идентификатора, например https://contoso.vault.azure.net/keys/data-protection
, не помещается GUID ключа.
Чтобы приложение взаимодействовало и авторизулось с помощью Azure Key Vault, Azure.Identity
пакет NuGet должен ссылаться на приложение.
Note
Рекомендации по добавлению пакетов в приложения .NET см. в статьях в разделе "Установка пакетов и управление пакетами" в рабочем процессе потребления пакетов (документация NuGet). Проверьте правильность версий пакета на сайте NuGet.org.
Note
В непроизводственных средах приведенный выше пример используется для упрощения проверки подлинности при разработке приложений, развертываемых в Azure, путем объединения учетных данных, используемых в средах хостинга Azure, с учетными данными, используемыми в процессе локальной разработки. Дополнительные сведения см. в статье Аутентификация размещенных в Azure приложений .NET в ресурсах Azure с помощью управляемого удостоверения, назначаемого системой.
Если приложение использует старые пакеты Azure (Microsoft.AspNetCore.DataProtection.AzureStorage
и Microsoft.AspNetCore.DataProtection.AzureKeyVault
), рекомендуется удалить эти ссылки и обновить их до Azure.Extensions.AspNetCore.DataProtection.Blobs
пакетов Azure.Extensions.AspNetCore.DataProtection.Keys
. Новые пакеты устраняют ключевые проблемы безопасности и стабильности.
Альтернативный подход подписанного URL-адреса (SAS): в качестве альтернативы использованию управляемого Identity для доступа к ключевому BLOB-объекту в хранилище BLOB-объектов Azure можно вызвать PersistKeysToAzureBlobStorage перегрузку, принимающую универсальный код ресурса (URI) BLOB-объектов с маркером SAS. Следующий пример продолжает использовать либо ManagedIdentityCredential (рабочую) или DefaultAzureCredential (разработка и тестирование) для TokenCredential, как показано в предшествующем примере.
builder.Services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
{APPLICATION NAME}
: SetApplicationName задает уникальное имя этого приложения в системе защиты данных. Значение должно совпадать между развертываниями приложения.
{BLOB URI WITH SAS}
: полный URI, в котором файл ключа должен храниться с маркером SAS в качестве параметра строки запроса. URI создается службой хранилища Azure при запросе SAS для загруженного файла ключа.
{KEY IDENTIFIER}
: идентификатор ключа Azure Key Vault, используемый для шифрования ключей. Политика доступа позволяет приложению получать доступ к хранилищу ключей с разрешениями Get
, Unwrap Key
и Wrap Key
. Версия ключа получается из ключа на портале Entra или Azure после его создания. Если включить автоматическое вращение ключа хранилища, убедитесь, что в конфигурации хранилища ключей приложения используется идентификатор ключа без версии, где в конце идентификатора, например https://contoso.vault.azure.net/keys/data-protection
, не помещается GUID ключа.
Сохранение ключей в файловой системе (PersistKeysToFileSystem
)
Чтобы хранить ключи на UNC-ресурсе вместо расположения по умолчанию %LOCALAPPDATA%, настройте систему с помощью PersistKeysToFileSystem:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
Warning
Если изменить расположение сохраняемости ключа, система больше не шифрует неактивные ключи, так как он не знает, является ли DPAPI соответствующим механизмом шифрования.
Сохранение ключей в базе данных (PersistKeysToDbContext
)
Чтобы сохранить ключи в базе данных с помощью EntityFramework, настройте систему с помощью пакета Microsoft.AspNetCore.DataProtection.EntityFrameworkCore :
builder.Services.AddDataProtection()
.PersistKeysToDbContext<SampleDbContext>();
Предыдущий код хранит ключи в настроенной базе данных. Контекст базы данных, используемый, должен реализовать IDataProtectionKeyContext
.
IDataProtectionKeyContext
предоставляет свойство DataProtectionKeys
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = null!;
Это свойство представляет таблицу, в которой хранятся ключи. Создайте таблицу вручную или с помощью DbContext
миграций. Дополнительные сведения см. в разделе DataProtectionKey.
Защита настройки ключей API (ProtectKeysWith\*
)
Вы можете настроить систему для защиты ключей в состоянии покоя, используя любой из API конфигурации. Рассмотрим приведенный ниже пример, в котором хранятся ключи в UNC-ресурсе и шифруются эти ключи с определенным сертификатом X.509.
Вы можете предоставить X509Certificate2 для ProtectKeysWithCertificate из файла, вызвав X509CertificateLoader.LoadCertificateFromFile.
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));
В следующем примере кода показано, как загрузить сертификат с помощью отпечатка:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);
Вы можете предоставить X509Certificate2 для ProtectKeysWithCertificate, например, сертификат, загруженный из файла:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));
В следующем примере кода показано, как загрузить сертификат с помощью отпечатка:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);
Примеры и обсуждение встроенных механизмов шифрования ключей см. в разделе "Шифрование ключей" в Windows и Azure с помощью ASP.NET Core.
Отмена защиты ключей с любым сертификатом (UnprotectKeysWithAnyCertificate
)
Вы можете обновить сертификаты и расшифровать хранящиеся ключи с помощью массива X509Certificate2 сертификатов с UnprotectKeysWithAnyCertificate:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]))
.UnprotectKeysWithAnyCertificate(
new X509Certificate2("certificate_1.pfx", builder.Configuration["CertificatePassword_1"]),
new X509Certificate2("certificate_2.pfx", builder.Configuration["CertificatePassword_2"]));
Установка времени существования ключа по умолчанию (SetDefaultKeyLifetime
)
Чтобы настроить систему для использования времени существования ключа в течение 14 дней вместо 90 дней по умолчанию, используйте SetDefaultKeyLifetimeследующую команду:
builder.Services.AddDataProtection()
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
Установите имя приложения (SetApplicationName
)
По умолчанию система защиты данных изолирует приложения друг от друга на основе корневых путей содержимого, даже если они совместно используют один и тот же репозиторий физических ключей. Эта изоляция мешает приложениям понимать защищенные полезные данные других приложений.
Для обмена защищенными полезными данными между приложениями:
- Настройте SetApplicationName в каждом приложении с одинаковым значением.
- Используйте ту же версию стека API защиты данных в приложениях. Выполните одно из следующих действий в файлах проектов приложений:
- Ссылка на ту же общую версию платформы с помощью метапакета Microsoft.AspNetCore.App.
- Ссылка на ту же версию пакета защиты данных.
builder.Services.AddDataProtection()
.SetApplicationName("<sharedApplicationName>");
SetApplicationName внутренне устанавливает DataProtectionOptions.ApplicationDiscriminator. В целях устранения неполадок значение, назначенное дискриминатором фреймворком, можно записать с использованием следующего кода, помещенного после сборки WebApplication в Program.cs
:
var discriminator = app.Services.GetRequiredService<IOptions<DataProtectionOptions>>()
.Value.ApplicationDiscriminator;
app.Logger.LogInformation("ApplicationDiscriminator: {ApplicationDiscriminator}", discriminator);
Дополнительные сведения о том, как используется дискриминация, см. в следующих разделах ниже в этой статье:
Warning
В .NET 6 WebApplicationBuilder нормализует корневой путь содержимого, чтобы он оканчивался на DirectorySeparatorChar. Например, в Windows корневой путь содержимого заканчивается на \
, а в Linux - на /
. Другие узлы не нормализуют путь. Большинство приложений, которые переносятся из HostBuilder или WebHostBuilder, не будут иметь одинаковое имя приложения, так как они не будут иметь завершающего DirectorySeparatorChar
. Чтобы обойти эту проблему, удалите символ разделителя каталогов и задайте имя приложения вручную, как показано в следующем коде:
using System.Reflection;
using Microsoft.AspNetCore.DataProtection;
var builder = WebApplication.CreateBuilder(args);
var trimmedContentRootPath =
builder.Environment.ContentRootPath.TrimEnd(Path.DirectorySeparatorChar);
builder.Services.AddDataProtection().SetApplicationName(trimmedContentRootPath);
var app = builder.Build();
app.MapGet("/", () => Assembly.GetEntryAssembly()!.GetName().Name);
app.Run();
Отключение автоматического создания ключей (DisableAutomaticKeyGeneration
)
Возможно, у вас есть ситуация, в которой приложение не следует автоматически менять ключи (создавать новые ключи), по мере истечения их срока действия. Одним из примеров этого сценария может быть приложение, настроенные в первично-вторичных отношениях, где только основное приложение отвечает за управление ключами, а вторичные приложения имеют только просмотр кольца ключей. Вторичные приложения можно настроить для работы с кольцом ключей в режиме только для чтения, настроив систему с помощью DisableAutomaticKeyGeneration.
builder.Services.AddDataProtection()
.DisableAutomaticKeyGeneration();
Per-application isolation
Если система защиты данных предоставляется узлом ASP.NET Core, она автоматически изолирует приложения друг от друга, даже если эти приложения выполняются под одной учетной записью рабочего процесса и используют один и тот же главный материал ключей. Это аналогично модификатору IsolateApps из элемента System.Web <machineKey>
.
Механизм изоляции работает, рассматривая каждое приложение на локальной машине как уникального арендатора, таким образом IDataProtector, корневой каталог для любого конкретного приложения автоматически включает идентификатор приложения как различающий признак (ApplicationDiscriminator). Уникальный идентификатор приложения — это физический путь приложения:
- Для приложений, размещенных в IIS, уникальный идентификатор — это физический путь к приложению IIS. Если приложение развертывается в среде веб-фермы, это значение стабильно предполагает, что среды IIS настроены одинаково на всех компьютерах в веб-ферме.
- Для локальных приложений, работающих на сервереKestrel, уникальный идентификатор — это физический путь к приложению на диске.
Уникальный идентификатор предназначен для того, чтобы сохраняться как при сбросе отдельного приложения, так и при сбросе самого компьютера.
Этот механизм изоляции предполагает, что приложения не являются вредоносными. Вредоносное приложение всегда может повлиять на любое другое приложение, работающее в той же учетной записи рабочего процесса. В общей среде размещения, в которой приложения являются взаимно ненадежными, поставщик должен предпринять меры для обеспечения изоляции на уровне ОС между приложениями, включая разделение их базовых хранилищ ключей.
Если система защиты данных не предоставляется хостом ASP.NET Core (например, если вы создаете экземпляр с помощью конкретного типа DataProtectionProvider
), изоляция приложений отключена по умолчанию. Если изоляция приложений отключена, все приложения, поддерживаемые одним и тем же ключевым материалом, могут совместно использовать нагрузки, если они предоставляют соответствующие цели. Чтобы обеспечить изоляцию приложений в этой среде, вызовите SetApplicationName
метод в объекте конфигурации и укажите уникальное имя для каждого приложения.
Защита данных и изоляция приложений
Рассмотрим следующие моменты для изоляции приложений:
При настройке нескольких приложений на использование одного и того же репозитория ключей намерение заключается в том, чтобы приложения делили один и тот же материал мастер-ключа. Защита данных разрабатывается с предположением, что все приложения, совместно использующие кольцо ключей, могут получить доступ ко всем элементам в этом круге ключей. Уникальный идентификатор приложения используется для изоляции ключей приложения, производных от ключей, предоставленных кольцом ключей. Он не ожидает, что разрешения на уровне элементов, такие как предоставленные Azure KeyVault, будут использоваться для принудительной дополнительной изоляции. При попытке назначения разрешений на уровне элементов возникают ошибки приложения. Если вы не хотите полагаться на встроенную изоляцию приложений, следует использовать отдельные расположения хранилища ключей и не предоставлять общий доступ между приложениями.
Дискриминатор приложения (ApplicationDiscriminator) используется для предоставления разным приложениям общего доступа к одному и тому же материалу мастер-ключа, но для сохранения их криптографических данных отдельно друг от друга. Чтобы приложения могли читать криптографические полезные данные друг друга, они должны иметь одинаковый дискриминатор приложения, который можно задать, вызвав
SetApplicationName
.Если приложение скомпрометировано (например, атакой RCE), все основные материалы ключей, доступные для этого приложения, также должны рассматриваться как скомпрометированные независимо от состояния защиты. Это означает, что если два приложения указываются на один репозиторий, даже если они используют разные идентификаторы приложений, компрометация одного из них функционально эквивалентна компрометации обоих.
Эта "функционально эквивалентная компромиссу обоих приложений" оговорка остается в силе, даже если два приложения используют разные механизмы защиты ключей на месте хранения. Как правило, это не ожидаемая конфигурация. Механизм защиты данных в состоянии покоя предназначен для обеспечения защиты в случае, если киберзлоумышленник получает доступ на чтение к репозиторию. Кибератакующий, который получает доступ к репозиторию на запись (возможно, потому что он получил разрешение на выполнение кода в приложении), может вставить вредоносные ключи в хранилище. Система защиты данных намеренно не обеспечивает защиту от кибератаки, которая получает доступ для записи в репозиторий ключей.
Если приложения должны оставаться действительно изолированными друг от друга, они должны использовать разные репозитории ключей. Это естественно выходит из определения "изолированных". Приложения не изолированы, если у всех них есть доступ на чтение и запись к хранилищам данных друг друга.
Изменение алгоритмов с помощью UseCryptographicAlgorithms
Стек защиты данных позволяет изменить алгоритм по умолчанию, используемый только что созданными ключами. Самый простой способ сделать это — вызвать UseCryptographicAlgorithms из обратного вызова конфигурации.
builder.Services.AddDataProtection()
.UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
По умолчанию, алгоритм шифрования — AES-256-CBC, а алгоритм проверки — HMACSHA256. Политика по умолчанию может быть задана системным администратором с помощью общесистемной политики, но явный вызов UseCryptographicAlgorithms
переопределяет политику по умолчанию.
Вызов UseCryptographicAlgorithms
позволяет указать требуемый алгоритм из предопределенного встроенного списка. Вам не нужно беспокоиться о реализации алгоритма. В приведенном выше сценарии система защиты данных пытается использовать реализацию AES CNG при запуске в Windows. В противном случае он возвращается в управляемый System.Security.Cryptography.Aes класс.
Можно вручную указать реализацию с помощью вызова UseCustomCryptographicAlgorithms.
Tip
Изменение алгоритмов не влияет на существующие ключи в кольце ключей. Это влияет только на недавно созданные ключи.
Указание пользовательских управляемых алгоритмов
Чтобы указать пользовательские управляемые алгоритмы, создайте экземпляр ManagedAuthenticatedEncryptorConfiguration, который ссылается на типы реализации:
builder.Services.AddDataProtection()
.UseCustomCryptographicAlgorithms(new ManagedAuthenticatedEncryptorConfiguration
{
// A type that subclasses SymmetricAlgorithm
EncryptionAlgorithmType = typeof(Aes),
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// A type that subclasses KeyedHashAlgorithm
ValidationAlgorithmType = typeof(HMACSHA256)
});
Как правило, свойства *Type должны ссылаться на конкретные, которые можно создать (через открытые методы ctor без параметров), реализации SymmetricAlgorithm и KeyedHashAlgorithm, хотя система делает исключения для некоторых значений, таких как typeof(Aes)
, для удобства.
Note
Симметричный алгоритм должен иметь длину ключа не менее 128 бит и размер блока не менее 64 бит, и он должен поддерживать шифрование в режиме CBC с заполнением по стандарту PKCS #7. KeyedHashAlgorithm должен иметь размер >дайджеста = 128 бит, и он должен поддерживать ключи длины, равной длине хэш-алгоритма. Алгоритм KeyedHashAlgorithm не обязательно должен быть HMAC.
Задача указания пользовательских алгоритмов Windows CNG
Чтобы указать алгоритм CNG Windows в пользовательском исполнении с использованием шифрования в режиме CBC и проверкой HMAC, создайте CngCbcAuthenticatedEncryptorConfiguration экземпляр, содержащий информацию об алгоритме:
builder.Services.AddDataProtection()
.UseCustomCryptographicAlgorithms(new CngCbcAuthenticatedEncryptorConfiguration
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// Passed to BCryptOpenAlgorithmProvider
HashAlgorithm = "SHA256",
HashAlgorithmProvider = null
});
Note
Алгоритм шифра симметричного блока должен иметь длину >ключа = 128 бит, размер >блока = 64 бита, и он должен поддерживать шифрование в режиме CBC с помощью PKCS #7. Хэш-алгоритм должен иметь размер хэша >= 128 бит и должен поддерживать возможность открытия с помощью флага BCRYPT_ALG_HANDLE_HMAC_FLAG. Свойства *Provider можно задать NULL, чтобы использовать поставщика по умолчанию для указанного алгоритма. Дополнительные сведения см. в документации BCryptOpenAlgorithmProvider .
Чтобы указать пользовательский алгоритм CNG Windows с использованием шифрования в режиме Galois/Counter и проверки, создайте экземпляр CngGcmAuthenticatedEncryptorConfiguration, содержащий алгоритмическую информацию:
builder.Services.AddDataProtection()
.UseCustomCryptographicAlgorithms(new CngGcmAuthenticatedEncryptorConfiguration
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256
});
Note
Алгоритм шифра симметричного блока должен иметь длину >ключа = 128 бит, размер блока ровно 128 бит, и он должен поддерживать шифрование GCM. Вы можете установить свойству значение EncryptionAlgorithmProvider на null, чтобы использовать провайдера по умолчанию для указанного алгоритма. Дополнительные сведения см. в документации BCryptOpenAlgorithmProvider .
Указание других настраиваемых алгоритмов
Хотя и не предоставляется в качестве API первого класса, система защиты данных достаточно расширяема, чтобы разрешить указание почти любого типа алгоритма. Например, можно сохранить все ключи, содержащиеся в аппаратном модуле безопасности (HSM), и предоставить настраиваемую реализацию основных процедур шифрования и расшифровки. Дополнительные сведения см. в статье IAuthenticatedEncryptor о расширяемости криптографии Core.
Обеспечение сохранности ключей при размещении в контейнере Docker
При размещении в контейнере Docker ключи должны храниться в любом из следующих элементов:
- Папка, которая является томом Docker, который сохраняется за пределами времени существования контейнера, например общий том или том, подключенный к узлу.
- Внешний поставщик, такой как Хранилище BLOB-объектов Azure (как показано в
ProtectKeysWithAzureKeyVault
разделе) или Redis.
Сохранение ключей с помощью Redis
Для хранения ключей следует использовать только версии Redis, поддерживающие сохраняемость данных Redis. Хранилище BLOB-объектов Azure является постоянным и может использоваться для хранения ключей. Дополнительные сведения см. здесь на GitHub.
Logging
Включите уровень ведения журнала Information
или ниже для диагностики проблем. Данный appsettings.json
файл включает регистрацию информации API защиты данных.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.DataProtection": "Information"
}
},
"AllowedHosts": "*"
}
Дополнительные сведения о ведении журнала см. в разделе "Ведение журнала" в .NET и ASP.NET Core.
Additional resources
При инициализации системы защиты данных она применяет параметры по умолчанию в зависимости от операционной среды. Эти параметры подходят для приложений, работающих на одном компьютере. Однако есть случаи, когда разработчику может потребоваться изменить параметры по умолчанию:
- Приложение распространяется на несколько компьютеров.
- По соображениям соответствия требованиям.
В этих сценариях система защиты данных предлагает широкий API конфигурации.
Warning
Как и в файлах конфигурации, кольцо ключей защиты данных должно быть защищено с помощью соответствующих разрешений. Вы можете зашифровать неактивные ключи, но это не предотвращает создание новых ключей злоумышленниками. Следовательно, это влияет на безопасность вашего приложения. Местоположение хранилища, настроенного с Data Protection, должно иметь доступ ограниченный только для самого приложения, аналогично тому, как защищаются файлы конфигурации. Например, если вы решили сохранить кольцо ключей на диске, используйте разрешения файловой системы. Убедитесь, что только учетная запись, под которой выполняется ваше веб-приложение, имеет права на чтение, запись и создание в этом каталоге. При использовании хранилища BLOB-объектов Azure только веб-приложение должно иметь возможность читать, записывать или создавать новые записи в хранилище BLOB-объектов.
Метод расширения AddDataProtection возвращает объект IDataProtectionBuilder, который предоставляет методы расширения, позволяющие их объединять для настройки параметров защиты данных.
Для расширений защиты данных, используемых в этой статье, требуются следующие пакеты NuGet:
Note
Рекомендации по добавлению пакетов в приложения .NET см. в статьях в разделе "Установка пакетов и управление пакетами" в рабочем процессе потребления пакетов (документация NuGet). Проверьте правильность версий пакета на сайте NuGet.org.
Защита ключей с помощью Azure Key Vault (ProtectKeysWithAzureKeyVault
)
Чтобы взаимодействовать с Azure Key Vault локально с помощью учетных данных разработчика, войдите в учетную запись хранения в Visual Studio или войдите в Azure CLI. Если вы еще не установили Azure CLI, см. инструкции по установке Azure CLI. Следующую команду можно выполнить на панели PowerShell разработчика в Visual Studio или из командной оболочки, если не использовать Visual Studio:
az login
Дополнительные сведения см. в статье "Вход в Azure с помощью средств разработчика".
При создании хранилища ключей в портале Entra или Azure:
Настройте хранилище ключей для использования управления доступом на основе ролей Azure (RABC). Если вы не работаете в виртуальной сети Azure, в том числе для локальной разработки и тестирования, убедитесь, что общедоступный доступ на шаге "Сеть " включен (установлен). Включение общедоступного доступа предоставляет только конечную точку хранилища ключей. Учетные записи, прошедшие проверку подлинности, по-прежнему необходимы для доступа.
Создайте управляемую Identity Azure роль (или добавьте роль в существующий управляемый Identity объект, который планируется использовать) с ролью пользователя шифрования Key Vault . Назначьте управляемую Identity учетную запись службе приложений Azure, который размещает развертывание: Параметры>Identity>Назначено пользователем>Добавить.
Note
Если вы также планируете локально запустить приложение с авторизованным пользователем для доступа к объектам Blob с помощью Azure CLI или проверки подлинности службы Azure в Visual Studio, добавьте учетную запись разработчика пользователя Azure в службе управления доступом (IAM) с ролью Key Vault Crypto User. Если вы хотите использовать Azure CLI через Visual Studio, выполните
az login
команду на панели PowerShell разработчика и следуйте инструкциям по проверке подлинности с помощью клиента.Если шифрование ключей активно, ключи в файле ключей включают комментарий "This key is encrypted with Azure Key Vault." После запуска приложения выберите команду View/edit в контекстном меню в конце строки ключа, чтобы убедиться, что ключ присутствует с примененной безопасностью хранилища ключей.
При необходимости можно включить автоматическую ротацию ключей в Key Vault без необходимости беспокоиться о расшифровке данных с использованием ключей защиты данных, основанных на истекших или обновленных ключах. Каждый созданный ключ защиты данных содержит ссылку на ключ хранилища ключей, используемый для шифрования. Просто убедитесь, что вы сохранили ключи хранилища ключей с истекшим сроком действия, не удаляйте их в хранилище ключей. Кроме того, используйте идентификатор ключа без версии в конфигурации хранилища ключей приложения, где в конце идентификатора (например,
https://contoso.vault.azure.net/keys/data-protection
) не помещается GUID ключа. Используйте аналогичный срок действия для обоих ключей, при этом ключ хранилища обновляется чаще, чем ключ защиты данных, чтобы гарантировать использование нового ключа хранилища во время обновления ключа защиты данных.
Защита ключей с помощью Azure Key Vault реализует IXmlEncryptor, который отключает параметры автоматической защиты данных, включая местоположение хранилища для кольца ключей. Чтобы настроить поставщик хранилища BLOB-объектов Azure для хранения ключей в хранилище BLOB-объектов, следуйте указаниям поставщиков хранилища ключей в ASP.NET Core и вызовите одну из PersistKeysToAzureBlobStorage перегрузок в приложении. В следующем примере используется перегрузка, принимающая URI блоба и токен аутентификационных данных (TokenCredential), с использованием управляемого идентификатора Azure для контроля доступа на основе ролей (RBAC).
Чтобы настроить провайдера Azure Key Vault, вызовите одну из перегрузок ProtectKeysWithAzureKeyVault. В следующем примере используется перегрузка, которая принимает идентификатор ключа и учетные данные токена (TokenCredential), полагаясь на управляемый Identity для RBAC в производстве (ManagedIdentityCredential) или DefaultAzureCredential во время разработки и тестирования. Другие перегрузки принимают клиента хранилища ключей или идентификатор клиента приложения с секретным ключом клиента. Дополнительные сведения см. в статье Поставщики хранилища ключей в ASP.NET Core.
Дополнительные сведения об API и проверке подлинности пакета SDK Azure см. в статье Аутентификация приложений .NET в службах Azure с помощью библиотеки Azure Identity и предоставление доступа к ключам Key Vault, сертификатам и секретам с помощью управления доступом на основе ролей Azure. Инструкции по ведению журнала см. в статье "Ведение журнала с помощью пакета SDK Azure для .NET: ведение журнала без регистрации клиента". Для приложений, использующих внедрение зависимостей, приложение может вызывать AddAzureClientsCore, передавая true
для enableLogForwarding
, чтобы создать и настроить логирующую инфраструктуру.
Program
В файле, где зарегистрированы службы:
TokenCredential? credential;
if (builder.Environment.IsProduction())
{
credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
// Local development and testing only
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = "{TENANT ID}",
SharedTokenCacheTenantId = "{TENANT ID}"
};
credential = new DefaultAzureCredential(options);
}
services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
{MANAGED IDENTITY CLIENT ID}
: идентификатор управляемого Identity клиента Azure (GUID).
{TENANT ID}
: идентификатор клиента.
{APPLICATION NAME}
: SetApplicationName задает уникальное имя этого приложения в системе защиты данных. Значение должно совпадать между развертываниями приложения.
{BLOB URI}
: полный универсальный код ресурса (URI) к файлу ключа. Код URI создается службой хранилища Azure при создании файла ключа. Не используйте SAS.
{KEY IDENTIFIER}
: идентификатор ключа Azure Key Vault, используемый для шифрования ключей. Политика доступа позволяет приложению получать доступ к хранилищу ключей с разрешениями Get
, Unwrap Key
и Wrap Key
. Версия ключа получается из ключа на портале Entra или Azure после его создания. Если включить автоматическое вращение ключа хранилища, убедитесь, что в конфигурации хранилища ключей приложения используется идентификатор ключа без версии, где в конце идентификатора, например https://contoso.vault.azure.net/keys/data-protection
, не помещается GUID ключа.
Чтобы приложение взаимодействовало и авторизулось с помощью Azure Key Vault, Azure.Identity
пакет NuGet должен ссылаться на приложение.
Note
Рекомендации по добавлению пакетов в приложения .NET см. в статьях в разделе "Установка пакетов и управление пакетами" в рабочем процессе потребления пакетов (документация NuGet). Проверьте правильность версий пакета на сайте NuGet.org.
Note
В непроизводственных средах приведенный выше пример используется для упрощения проверки подлинности при разработке приложений, развертываемых в Azure, путем объединения учетных данных, используемых в средах хостинга Azure, с учетными данными, используемыми в процессе локальной разработки. Дополнительные сведения см. в статье Аутентификация размещенных в Azure приложений .NET в ресурсах Azure с помощью управляемого удостоверения, назначаемого системой.
Если приложение использует старые пакеты Azure (Microsoft.AspNetCore.DataProtection.AzureStorage
и Microsoft.AspNetCore.DataProtection.AzureKeyVault
), рекомендуется удалить эти ссылки и обновить их до Azure.Extensions.AspNetCore.DataProtection.Blobs
пакетов Azure.Extensions.AspNetCore.DataProtection.Keys
. Новые пакеты устраняют ключевые проблемы безопасности и стабильности.
Альтернативный подход подписанного URL-адреса (SAS): в качестве альтернативы использованию управляемого Identity для доступа к ключевому BLOB-объекту в хранилище BLOB-объектов Azure можно вызвать PersistKeysToAzureBlobStorage перегрузку, принимающую универсальный код ресурса (URI) BLOB-объектов с маркером SAS. Следующий пример продолжает использовать либо ManagedIdentityCredential (рабочую) или DefaultAzureCredential (разработка и тестирование) для TokenCredential, как показано в предшествующем примере.
services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
{APPLICATION NAME}
: SetApplicationName задает уникальное имя этого приложения в системе защиты данных. Значение должно совпадать между развертываниями приложения.
{BLOB URI WITH SAS}
: полный URI, в котором файл ключа должен храниться с маркером SAS в качестве параметра строки запроса. URI создается службой хранилища Azure при запросе SAS для загруженного файла ключа.
{KEY IDENTIFIER}
: идентификатор ключа Azure Key Vault, используемый для шифрования ключей. Политика доступа позволяет приложению получать доступ к хранилищу ключей с разрешениями Get
, Unwrap Key
и Wrap Key
. Версия ключа получается из ключа на портале Entra или Azure после его создания. Если включить автоматическое вращение ключа хранилища, убедитесь, что в конфигурации хранилища ключей приложения используется идентификатор ключа без версии, где в конце идентификатора, например https://contoso.vault.azure.net/keys/data-protection
, не помещается GUID ключа.
Сохранение ключей в файловой системе (PersistKeysToFileSystem
)
Чтобы хранить ключи на UNC-ресурсе вместо расположения по умолчанию %LOCALAPPDATA%, настройте систему с помощью PersistKeysToFileSystem:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
}
Warning
Если изменить расположение сохраняемости ключа, система больше не шифрует неактивные ключи, так как он не знает, является ли DPAPI соответствующим механизмом шифрования.
Сохранение ключей в базе данных (PersistKeysToDbContext
)
Чтобы сохранить ключи в базе данных с помощью EntityFramework, настройте систему с помощью пакета Microsoft.AspNetCore.DataProtection.EntityFrameworkCore :
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToDbContext<DbContext>()
}
Предыдущий код хранит ключи в настроенной базе данных. Контекст базы данных, используемый, должен реализовать IDataProtectionKeyContext
.
IDataProtectionKeyContext
предоставляет свойство DataProtectionKeys
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
Это свойство представляет таблицу, в которой хранятся ключи. Создайте таблицу вручную или с помощью DbContext
миграций. Дополнительные сведения см. в разделе DataProtectionKey.
Защита настройки ключей API (ProtectKeysWith\*
)
Вы можете настроить систему для защиты ключей в состоянии покоя, используя любой из API конфигурации. Рассмотрим приведенный ниже пример, который сохраняет ключи на UNC-поделении и шифрует их в состоянии покоя с помощью определенного сертификата X.509:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(Configuration["Thumbprint"]);
}
Вы можете предоставить X509Certificate2 для ProtectKeysWithCertificate, например, сертификат, загруженный из файла:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", Configuration["Thumbprint"]));
}
Дополнительные примеры и обсуждение встроенных механизмов шифрования ключей см. в разделе "Шифрование ключей" в Windows и Azure с помощью ASP.NET Core.
Отмена защиты ключей с любым сертификатом (UnprotectKeysWithAnyCertificate
)
Вы можете обновить сертификаты и расшифровать хранящиеся ключи с помощью массива X509Certificate2 сертификатов с UnprotectKeysWithAnyCertificate:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", Configuration["MyPasswordKey"));
.UnprotectKeysWithAnyCertificate(
new X509Certificate2("certificate_old_1.pfx", Configuration["MyPasswordKey_1"]),
new X509Certificate2("certificate_old_2.pfx", Configuration["MyPasswordKey_2"]));
}
Установка времени существования ключа по умолчанию (SetDefaultKeyLifetime
)
Чтобы настроить систему для использования времени существования ключа в течение 14 дней вместо 90 дней по умолчанию, используйте SetDefaultKeyLifetimeследующую команду:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}
Установите имя приложения (SetApplicationName
)
По умолчанию система защиты данных изолирует приложения друг от друга на основе корневых путей содержимого, даже если они совместно используют один и тот же репозиторий физических ключей. Эта изоляция мешает приложениям понимать защищенные полезные данные других приложений.
Для обмена защищенными полезными данными между приложениями:
- Настройте SetApplicationName в каждом приложении с одинаковым значением.
- Используйте ту же версию стека API защиты данных в приложениях. Выполните одно из следующих действий в файлах проектов приложений:
- Ссылка на ту же общую версию платформы с помощью метапакета Microsoft.AspNetCore.App.
- Ссылка на ту же версию пакета защиты данных.
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}");
}
SetApplicationName внутренне устанавливает DataProtectionOptions.ApplicationDiscriminator. Дополнительные сведения о том, как используется дискриминация, см. в следующих разделах ниже в этой статье:
Отключение автоматического создания ключей (DisableAutomaticKeyGeneration
)
Возможно, у вас есть ситуация, в которой приложение не следует автоматически менять ключи (создавать новые ключи), по мере истечения их срока действия. Одним из примеров этого сценария может быть приложение, настроенные в первично-вторичных отношениях, где только основное приложение отвечает за управление ключами, а вторичные приложения имеют только просмотр кольца ключей. Вторичные приложения можно настроить для работы с кольцом ключей в режиме только для чтения, настроив систему с помощью DisableAutomaticKeyGeneration.
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.DisableAutomaticKeyGeneration();
}
Per-application isolation
Если система защиты данных предоставляется узлом ASP.NET Core, она автоматически изолирует приложения друг от друга, даже если эти приложения выполняются под одной учетной записью рабочего процесса и используют один и тот же главный материал ключей. Это аналогично модификатору IsolateApps из элемента System.Web <machineKey>
.
Механизм изоляции работает, рассматривая каждое приложение на локальной машине как уникального арендатора, таким образом IDataProtector, корневой каталог для любого конкретного приложения автоматически включает идентификатор приложения как различающий признак (ApplicationDiscriminator). Уникальный идентификатор приложения — это физический путь приложения:
- Для приложений, размещенных в IIS, уникальный идентификатор — это физический путь к приложению IIS. Если приложение развертывается в среде веб-фермы, это значение стабильно предполагает, что среды IIS настроены одинаково на всех компьютерах в веб-ферме.
- Для локальных приложений, работающих на сервереKestrel, уникальный идентификатор — это физический путь к приложению на диске.
Уникальный идентификатор предназначен для того, чтобы сохраняться как при сбросе отдельного приложения, так и при сбросе самого компьютера.
Этот механизм изоляции предполагает, что приложения не являются вредоносными. Вредоносное приложение всегда может повлиять на любое другое приложение, работающее в той же учетной записи рабочего процесса. В общей среде размещения, в которой приложения являются взаимно ненадежными, поставщик должен предпринять меры для обеспечения изоляции на уровне ОС между приложениями, включая разделение их базовых хранилищ ключей.
Если система защиты данных не предоставляется хостом ASP.NET Core (например, если вы создаете экземпляр с помощью конкретного типа DataProtectionProvider
), изоляция приложений отключена по умолчанию. Если изоляция приложений отключена, все приложения, поддерживаемые одним и тем же ключевым материалом, могут совместно использовать нагрузки, если они предоставляют соответствующие цели. Чтобы обеспечить изоляцию приложений в этой среде, вызовите метод SetApplicationName в объекте конфигурации и укажите уникальное имя для каждого приложения.
Защита данных и изоляция приложений
Рассмотрим следующие моменты для изоляции приложений:
При настройке нескольких приложений на использование одного и того же репозитория ключей намерение заключается в том, чтобы приложения делили один и тот же материал мастер-ключа. Защита данных разрабатывается с предположением, что все приложения, совместно использующие кольцо ключей, могут получить доступ ко всем элементам в этом круге ключей. Уникальный идентификатор приложения используется для изоляции ключей приложения, производных от ключей, предоставленных кольцом ключей. Он не ожидает, что разрешения на уровне элементов, такие как предоставленные Azure KeyVault, будут использоваться для принудительной дополнительной изоляции. При попытке назначения разрешений на уровне элементов возникают ошибки приложения. Если вы не хотите полагаться на встроенную изоляцию приложений, следует использовать отдельные расположения хранилища ключей и не предоставлять общий доступ между приложениями.
Дискриминатор приложения (ApplicationDiscriminator) используется для предоставления разным приложениям общего доступа к одному и тому же материалу мастер-ключа, но для сохранения их криптографических данных отдельно друг от друга. Чтобы приложения могли читать криптографические полезные данные друг друга, они должны иметь одинаковый дискриминатор приложения, который можно задать, вызвав
SetApplicationName
.Если приложение скомпрометировано (например, атакой RCE), все основные материалы ключей, доступные для этого приложения, также должны рассматриваться как скомпрометированные независимо от состояния защиты. Это означает, что если два приложения указываются на один репозиторий, даже если они используют разные идентификаторы приложений, компрометация одного из них функционально эквивалентна компрометации обоих.
Эта "функционально эквивалентная компромиссу обоих приложений" оговорка остается в силе, даже если два приложения используют разные механизмы защиты ключей на месте хранения. Как правило, это не ожидаемая конфигурация. Механизм защиты данных в состоянии покоя предназначен для обеспечения защиты в случае, если киберзлоумышленник получает доступ на чтение к репозиторию. Кибератакующий, который получает доступ к репозиторию на запись (возможно, потому что он получил разрешение на выполнение кода в приложении), может вставить вредоносные ключи в хранилище. Система защиты данных намеренно не обеспечивает защиту от кибератаки, которая получает доступ для записи в репозиторий ключей.
Если приложения должны оставаться действительно изолированными друг от друга, они должны использовать разные репозитории ключей. Это естественно выходит из определения "изолированных". Приложения не изолированы, если у всех них есть доступ на чтение и запись к хранилищам данных друг друга.
Изменение алгоритмов с помощью UseCryptographicAlgorithms
Стек защиты данных позволяет изменить алгоритм по умолчанию, используемый только что созданными ключами. Самый простой способ сделать это — вызвать UseCryptographicAlgorithms из обратного вызова конфигурации.
services.AddDataProtection()
.UseCryptographicAlgorithms(
new AuthenticatedEncryptorConfiguration()
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
По умолчанию, алгоритм шифрования — AES-256-CBC, а алгоритм проверки — HMACSHA256. Политика по умолчанию может быть задана системным администратором с помощью общесистемной политики, но явный вызов UseCryptographicAlgorithms
переопределяет политику по умолчанию.
Вызов UseCryptographicAlgorithms
позволяет указать требуемый алгоритм из предопределенного встроенного списка. Вам не нужно беспокоиться о реализации алгоритма. В приведенном выше сценарии система защиты данных пытается использовать реализацию AES CNG при запуске в Windows. В противном случае он возвращается в управляемый System.Security.Cryptography.Aes класс.
Можно вручную указать реализацию с помощью вызова UseCustomCryptographicAlgorithms.
Tip
Изменение алгоритмов не влияет на существующие ключи в кольце ключей. Это влияет только на недавно созданные ключи.
Указание пользовательских управляемых алгоритмов
Чтобы указать пользовательские управляемые алгоритмы, создайте экземпляр ManagedAuthenticatedEncryptorConfiguration, который ссылается на типы реализации:
serviceCollection.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new ManagedAuthenticatedEncryptorConfiguration()
{
// A type that subclasses SymmetricAlgorithm
EncryptionAlgorithmType = typeof(Aes),
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// A type that subclasses KeyedHashAlgorithm
ValidationAlgorithmType = typeof(HMACSHA256)
});
Как правило, свойства *Type должны ссылаться на конкретные, которые можно создать (через открытые методы ctor без параметров), реализации SymmetricAlgorithm и KeyedHashAlgorithm, хотя система делает исключения для некоторых значений, таких как typeof(Aes)
, для удобства.
Note
Симметричный алгоритм должен иметь длину ключа не менее 128 бит и размер блока не менее 64 бит, и он должен поддерживать шифрование в режиме CBC с заполнением по стандарту PKCS #7. KeyedHashAlgorithm должен иметь размер >дайджеста = 128 бит, и он должен поддерживать ключи длины, равной длине хэш-алгоритма. Алгоритм KeyedHashAlgorithm не обязательно должен быть HMAC.
Задача указания пользовательских алгоритмов Windows CNG
Чтобы указать алгоритм CNG Windows в пользовательском исполнении с использованием шифрования в режиме CBC и проверкой HMAC, создайте CngCbcAuthenticatedEncryptorConfiguration экземпляр, содержащий информацию об алгоритме:
services.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new CngCbcAuthenticatedEncryptorConfiguration()
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// Passed to BCryptOpenAlgorithmProvider
HashAlgorithm = "SHA256",
HashAlgorithmProvider = null
});
Note
Алгоритм шифра симметричного блока должен иметь длину >ключа = 128 бит, размер >блока = 64 бита, и он должен поддерживать шифрование в режиме CBC с помощью PKCS #7. Хэш-алгоритм должен иметь размер хэша >= 128 бит и должен поддерживать возможность открытия с помощью флага BCRYPT_ALG_HANDLE_HMAC_FLAG. Свойства *Provider можно задать NULL, чтобы использовать поставщика по умолчанию для указанного алгоритма. Дополнительные сведения см. в документации BCryptOpenAlgorithmProvider .
Чтобы указать пользовательский алгоритм CNG Windows с использованием шифрования в режиме Galois/Counter и проверки, создайте экземпляр CngGcmAuthenticatedEncryptorConfiguration, содержащий алгоритмическую информацию:
services.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new CngGcmAuthenticatedEncryptorConfiguration()
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256
});
Note
Алгоритм шифра симметричного блока должен иметь длину >ключа = 128 бит, размер блока ровно 128 бит, и он должен поддерживать шифрование GCM. Вы можете установить свойству значение EncryptionAlgorithmProvider на null, чтобы использовать провайдера по умолчанию для указанного алгоритма. Дополнительные сведения см. в документации BCryptOpenAlgorithmProvider .
Указание других настраиваемых алгоритмов
Хотя и не предоставляется в качестве API первого класса, система защиты данных достаточно расширяема, чтобы разрешить указание почти любого типа алгоритма. Например, можно сохранить все ключи, содержащиеся в аппаратном модуле безопасности (HSM), и предоставить настраиваемую реализацию основных процедур шифрования и расшифровки. Дополнительные сведения см. в статье IAuthenticatedEncryptor о расширяемости криптографии Core.
Обеспечение сохранности ключей при размещении в контейнере Docker
При размещении в контейнере Docker ключи должны храниться в любом из следующих элементов:
- Папка, которая является томом Docker, который сохраняется за пределами времени существования контейнера, например общий том или том, подключенный к узлу.
- Внешний поставщик, например облачное хранилище Azure Blob (показан в разделе "Защита ключей с помощью Azure Key Vault (
ProtectKeysWithAzureKeyVault
)" или Redis.
Сохранение ключей с помощью Redis
Для хранения ключей следует использовать только версии Redis, поддерживающие сохраняемость данных Redis. Хранилище BLOB-объектов Azure является постоянным и может использоваться для хранения ключей. Дополнительные сведения см. здесь на GitHub.
Logging
Включите уровень ведения журнала Information
или ниже для диагностики проблем. Данный appsettings.json
файл включает регистрацию информации API защиты данных.
{
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.DataProtection": "Information"
}
}
}
Дополнительные сведения о ведении журнала см. в разделе "Ведение журнала" в .NET и ASP.NET Core.
Additional resources
ASP.NET Core