Расширяемость шифрования ядра в ASP.NET Core

Предупреждение

Типы, реализующие любой из следующих интерфейсов, должны быть потокобезопасны для нескольких вызывающих объектов.

IAuthenticatedEncryptor

Интерфейс IAuthenticatedEncryptor является основным стандартным блоком подсистемы шифрования. Как правило, есть один IAuthenticatedEncryptor на ключ, а экземпляр IAuthenticatedEncryptor упаковывает все материалы криптографического ключа и алгоритмические сведения, необходимые для выполнения криптографических операций.

Как предполагает его имя, тип отвечает за предоставление служб шифрования и расшифровки, прошедших проверку подлинности. Он предоставляет следующие два API.

  • Decrypt(ArraySegment<byte> ciphertext, ArraySegment<byte> additionalAuthenticatedData) : byte[]

  • Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additionalAuthenticatedData) : byte[]

Метод Encrypt возвращает большой двоичный объект, включающий зашифрованный открытый текст и тег проверки подлинности. Тег проверки подлинности должен охватывать дополнительные данные, прошедшие проверку подлинности (AAD), хотя сам AAD не должен быть восстановлен из окончательной полезных данных. Метод расшифровки проверяет тег проверки подлинности и возвращает расшифрованные полезные данные. Все ошибки (кроме ArgumentNullException и аналогичные) должны быть однородными для CryptographicException.

Примечание.

Сам экземпляр IAuthenticatedEncryptor не должен содержать материал ключа. Например, реализация может делегировать HSM для всех операций.

Создание IAuthenticatedEncryptor

Интерфейс IAuthenticatedEncryptorFactory представляет тип, который знает, как создать экземпляр IAuthenticatedEncryptor . Его API выглядит следующим образом.

  • CreateEncryptorInstance(ключ IKey) : IAuthenticatedEncryptor

Для любого конкретного экземпляра IKey все прошедшие проверку подлинности шифраторы, созданные его методом CreateEncryptorInstance, должны считаться эквивалентными, как в приведенном ниже примере кода.

// we have an IAuthenticatedEncryptorFactory instance and an IKey instance
IAuthenticatedEncryptorFactory factory = ...;
IKey key = ...;

// get an encryptor instance and perform an authenticated encryption operation
ArraySegment<byte> plaintext = new ArraySegment<byte>(Encoding.UTF8.GetBytes("plaintext"));
ArraySegment<byte> aad = new ArraySegment<byte>(Encoding.UTF8.GetBytes("AAD"));
var encryptor1 = factory.CreateEncryptorInstance(key);
byte[] ciphertext = encryptor1.Encrypt(plaintext, aad);

// get another encryptor instance and perform an authenticated decryption operation
var encryptor2 = factory.CreateEncryptorInstance(key);
byte[] roundTripped = encryptor2.Decrypt(new ArraySegment<byte>(ciphertext), aad);


// the 'roundTripped' and 'plaintext' buffers should be equivalent

IAuthenticatedEncryptorDescriptor (только ASP.NET Core 2.x)

Интерфейс IAuthenticatedEncryptorDescriptor представляет тип, который знает, как экспортировать себя в XML. Его API выглядит следующим образом.

  • ExportToXml() : XmlSerializedDescriptorInfo

Сериализация XML

Основное различие между IAuthenticatedEncryptor и IAuthenticatedEncryptorDescriptor заключается в том, что дескриптор знает, как создать шифратор и предоставить его допустимым аргументам. Рассмотрим IAuthenticatedEncryptor, реализация которого зависит от СимметричногоAlgorithm и KeyedHashAlgorithm. Задание шифратора заключается в том, чтобы использовать эти типы, но он не обязательно знает, откуда пришли эти типы, поэтому он не может действительно записать правильное описание того, как создать себя при перезапуске приложения. Дескриптор выступает в качестве более высокого уровня поверх этого. Так как дескриптор знает, как создать экземпляр шифратора (например, он знает, как создать необходимые алгоритмы), он может сериализовать эти знания в XML-форме, чтобы экземпляр шифратора можно было воссоздать после сброса приложения.

Дескриптор можно сериализовать с помощью подпрограммы ExportToXml. Эта подпрограмма возвращает XmlSerializedDescriptorInfo, которая содержит два свойства: представление дескриптора XElement и тип, представляющий IAuthenticatedEncryptorDescriptorDeserializer , который можно использовать для восстановления этого дескриптора с учетом соответствующего XElement.

Сериализованный дескриптор может содержать конфиденциальную информацию, например материал криптографического ключа. Система защиты данных имеет встроенную поддержку шифрования информации перед сохранением в хранилище. Чтобы воспользоваться этим, дескриптор должен пометить элемент, содержащий конфиденциальную информацию с именем атрибута "requirementsEncryption" (xmlns "<http://schemas.asp.net/2015/03/dataProtection>"), значение "true".

Совет

Существует вспомогательный API для настройки этого атрибута. Вызовите метод расширения XElement.MarkAsRequiresEncryption(), расположенный в пространстве имен Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.

Также могут возникнуть случаи, когда сериализованный дескриптор не содержит конфиденциальную информацию. Рассмотрим еще раз случай криптографического ключа, хранящегося в HSM. Дескриптор не может записать материал ключа при сериализации себя, так как HSM не будет предоставлять материал в виде открытого текста. Вместо этого дескриптор может записать версию ключа с оболочкой ключа (если HSM разрешает экспорт таким образом) или собственный уникальный идентификатор HSM для ключа.

IAuthenticatedEncryptorDescriptorDeserializer

Интерфейс IAuthenticatedEncryptorDescriptorDeserializer представляет тип, который знает, как десериализировать экземпляр IAuthenticatedEncryptorDescriptor из XElement. Он предоставляет один метод:

  • ImportFromXml(элемент XElement) : IAuthenticatedEncryptorDescriptor

Метод ImportFromXml принимает XElement, возвращенный IAuthenticatedEncryptorDescriptor.ExportToXml , и создает эквивалент исходного IAuthenticatedEncryptorDescriptor.

Типы, реализующие IAuthenticatedEncryptorDescriptorDeserializer, должны иметь один из следующих двух открытых конструкторов:

  • .ctor(IServiceProvider)

  • .ctor()

Примечание.

Объект IServiceProvider, переданный конструктору, может иметь значение NULL.

Фабрика верхнего уровня

Класс AlgorithmConfiguration представляет тип, который знает, как создавать экземпляры IAuthenticatedEncryptorDescriptor . Он предоставляет один API.

  • CreateNewDescriptor() : IAuthenticatedEncryptorDescriptor

Подумайте об алгоритмеConfiguration как фабрике верхнего уровня. Конфигурация служит шаблоном. Он упаковывает алгоритмические сведения (например, эта конфигурация создает дескрипторы с главным ключом AES-128-GCM), но он еще не связан с определенным ключом.

При вызове CreateNewDescriptor новый ключевой материал создается исключительно для этого вызова, и создается новый объект IAuthenticatedEncryptorDescriptorDescriptor, который упаковывает этот ключевой материал и алгоритмическую информацию, необходимую для использования материала. Ключевые материалы можно создать в программном обеспечении (и хранить в памяти), его можно создать и хранить в HSM и т. д. Важно отметить, что любые два вызова CreateNewDescriptor никогда не должны создавать эквивалентные экземпляры IAuthenticatedEncryptorDescriptor.

Тип AlgorithmConfiguration служит точкой входа для подпрограмм создания ключей, таких как автоматическое переключение ключей. Чтобы изменить реализацию для всех будущих ключей, задайте свойство AuthenticatedEncryptorConfiguration в KeyManagementOptions.