Использование зашифрованных моделей с Windows ML

Существует несколько статических методов, которые можно применить к классу LearningModel для загрузки моделей машинного обучения, таких как загрузка модели из файла в приложении, из файла на диске или загрузка модели из потока.

Загрузка из метода потока позволяет лучше управлять моделью. В этом случае вы можете зашифровать модель на диске и расшифровать ее только в памяти перед вызовом одного из методов LoadFromStream.

В этом руководстве вы узнаете, как интегрировать зашифрованную модель машинного обучения с приложением Windows ML (C#).

API машинного обучения Windows не предоставляют службу шифрования машинного обучения и не несут ответственности за какой-либо ущерб или потерю какого-либо вида.

Получить модель ONNX

В этом руководстве вы будете использовать модель SqueezeNet в формате ONNX для выполнения шифрования, расшифровки и загрузки из потока.

Скачайте или клонируйте пример приложения для обнаружения объектов SqueezeNet из GitHub, чтобы получить модель SqueezeNet.onnx.

Укажите необходимые объявления и переменные

  1. Скопируйте приведенные ниже объявления с помощью инструкций, чтобы получить доступ ко всем необходимым API:
using System;
using System.Threading.Tasks;
using Windows.AI.MachineLearning;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;

Вы определите две специальные переменные для ключа и вектора инициализации.

Ключ — это переменная класса CryptographicKey, представляющая симметричную пару ключей (или асимметричную). Вам потребуется объект из этого класса, так как вы будете использовать AsymmetricKeyAlgorithmProvider метод для создания или импорта ключей.

Вектор инициализации — это переменная класса IBuffer, представляющая указанный массив байтов, используемый потоками байтов чтения и записи.

Оба CryptographicKey и IBuffer переменные класса используются для шифрования и расшифровки потока.

  1. Добавьте следующие объявления переменных и MainPage класс после инструкций using в пространстве имен шифрования:
namespace crypto
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        private CryptographicKey _key;
        private IBuffer _initialization_vector;
        public MainPage()
        {
            this.InitializeComponent();

            Run();
        }
    }
}

Шифрование модели

API Windows предоставляют широкий набор функций и возможностей, которые могут улучшить функциональные возможности набора API Машинного обучения Windows. Здесь вы будете использовать службу шифрования и расшифровки, предоставляемую в API Windows, для создания потока в памяти и использования API Машинного обучения Windows для загрузки модели из этого потока.

Для шифрования модели машинного обучения можно использовать любую службу шифрования. В этом руководстве мы будем использовать метод шифрования — SymmetricAlgorithmNames - .AesCbcPkcs7.

Класс SymmetricAlgorithmNames помогает получить алгоритмы симметричного ключа для применения шифрования симметричного ключа в модели. Этот тип шифрования требует, чтобы тот же ключ, используемый для шифрования, также использовался для расшифровки.

SymmetricKeyAlgorithmProvider С помощью класса можно выбрать алгоритм и создать ключ. В этом руководстве мы используем алгоритм .AesCbcPkcs7..

Алгоритм AES_CBC_PKCS7 представляет расширенный алгоритм шифрования (AES), в сочетании с режимом цепочки блоков шифров и заполнением PKCS#7.

  1. В приведенном ниже коде показано, как создать ключ и зашифровать модель.
async Task<IBuffer> EncryptAsync(StorageFile model_file)
{
	// get a buffer for the model file
	var file_buffer = await Windows.Storage.FileIO.ReadBufferAsync(model_file);

	// set up the encryption algorithm
	var algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
	uint key_length = 32;
	var key_buffer = CryptographicBuffer.GenerateRandom(key_length);
	_key = algorithm.CreateSymmetricKey(key_buffer);
	_initialization_vector = CryptographicBuffer.GenerateRandom(algorithm.BlockLength);

	// perform the encryption
	var encrypted_buffer = CryptographicEngine.Encrypt(_key, file_buffer, _initialization_vector);

	return encrypted_buffer;
}

[ПРИМЕЧАНИЕ!] Хотите узнать больше о криптографических ключах? Ознакомьтесь с документацией по криптографическим ключам.

Расшифровка модели и загрузки из потока

Перед загрузкой модели необходимо расшифровать ее с помощью метода CryptographicEngine.Decrypt. CryptographicEngine.Decrypt — это метод расшифровки содержимого, ранее зашифрованного с помощью симметричного или асимметричного алгоритма. При вызове метода необходимо указать ранее созданный ключ.

Для доступа к расшифрованной модели используется InMemoryRandomAccessStream класс, который обеспечивает случайный доступ к данным во входных и выходных потоках, хранящихся в памяти, а не на диске.

В качестве последнего шага вы создадите сеанс для загрузки модели из потока с помощью LearningModel.LoadFromStreamAsync метода. Этот метод можно вызвать как синхронную или асинхронную задачу.

В приведенном ниже коде показано, как расшифровать модель с помощью созданного ключа, записать ее в поток, а затем загрузить модель из потока.

async Task DecryptAndRunAsync(IBuffer encryptyed_buffer)
{
	// decrypt the buffer
	var decrypted_buffer = CryptographicEngine.Decrypt(_key, encryptyed_buffer, _initialization_vector);

	// write it to a stream
	var decrypted_stream = new InMemoryRandomAccessStream();
	await decrypted_stream.WriteAsync(decrypted_buffer);

	// load the model from the stream
	var model = await LearningModel.LoadFromStreamAsync(RandomAccessStreamReference.CreateFromStream(decrypted_stream));

	// create a session
	var session = new LearningModelSession(model);
}

Запуск модели

Скопируйте следующий метод Run, чтобы вызвать методы, определенные ранее.

async Task Run()
{

	// get the model file
	var model_file = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/SqueezeNet.onnx"));

	// encrypt the model file.
	var encryptyed_buffer = await EncryptAsync(model_file);

	// decrypt the model file and load it
	await DecryptAndRunAsync(encryptyed_buffer);
}

Сводка

Вот и все! Модель успешно загружена в приложение Windows ML.

После загрузки модели можно продолжить создание сеанса, привязку входных и выходных данных модели и оценку модели для завершения приложения Windows ML.

Дополнительные ресурсы

Дополнительные сведения о разделах, упомянутых в этом руководстве, см. в следующих ресурсах: