Usar modelos criptografados com o Windows ML

Há vários métodos estáticos que podemos aplicar na classe LearningModel para carregar modelos de aprendizado de máquina, como carregar o modelo de um arquivo em seu aplicativo, de um arquivo em disco ou carregar um modelo de um fluxo.

O carregamento a partir de um método de fluxo permite um melhor controlo sobre o modelo. Nesse caso, você pode optar por ter o modelo criptografado no disco e descriptografá-lo somente na memória antes de chamar um dos métodos LoadFromStream.

Neste tutorial, você aprenderá como integrar um modelo de aprendizado de máquina criptografado com o aplicativo Windows ML (C#).

As APIs de ML do Windows não fornecem serviço de criptografia de aprendizado de máquina e não serão responsabilizadas por qualquer dano ou perda de qualquer tipo.

Obtenha o modelo ONNX

Neste tutorial, você usará o modelo SqueezeNet no formato ONNX para executar a criptografia, descriptografia e carregamento do fluxo.

Baixe ou clone o aplicativo de exemplo SqueezeNet Object Detection do GitHub para obter o modelo SqueezeNet.onnx.

Especificar as declarações e variáveis necessárias

  1. Copie abaixo as declarações de instrução para obter acesso a todas as APIs de que precisará.
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;

Você definirá duas variáveis especiais para uma chave e um vetor de inicialização.

A chave é uma variável da classe CryptographicKey, que representa um par de chaves simétrico (ou assimétrico). Você precisará de um objeto dessa classe, pois usará o AsymmetricKeyAlgorithmProvider método para criar ou importar chaves.

O vetor de inicialização é uma variável da classe IBuffer, que representa uma matriz referenciada de bytes usados por interfaces de leitura e gravação de fluxo de bytes.

Tanto CryptographicKey como IBuffer são variáveis de classe usadas para criptografar e descriptografar o fluxo.

  1. Adicione as seguintes declarações de variável e a classe MainPage após as instruções using dentro do espaço de nomes criptográfico.
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();
        }
    }
}

Criptografar o modelo

As APIs do Windows fornecem um conjunto avançado de recursos e capacidades, que podem aprimorar a funcionalidade do conjunto de APIs do Windows ML. Aqui, você usará um serviço de criptografia e descriptografia fornecido no conjunto de APIs do Windows para produzir um fluxo na memória e usará APIs de ML do Windows para carregar o modelo desse fluxo.

Você pode usar qualquer serviço de criptografia para criptografar seu modelo de aprendizado de máquina, de acordo com sua conveniência. Neste tutorial, usaremos o método de criptografia – SymmetricAlgorithmNames - .AesCbcPkcs7.

A classe SymmetricAlgorithmNames ajuda você a recuperar algoritmos de chave simétrica para aplicar criptografia de chave simétrica em seu modelo. Este tipo de encriptação requer que a mesma chave usada para encriptação também seja usada para desencriptação.

Usando a SymmetricKeyAlgorithmProvider classe, você pode selecionar um algoritmo e criar sua chave. Neste tutorial, usaremos o .AesCbcPkcs7. algoritmo.

O AES_CBC_PKCS7 algoritmo representa um algoritmo AES (Encryption Standard) avançado, juntamente com um modo de operação de encadeamento de blocos de cifra e preenchimento PKCS#7.

  1. O código abaixo mostra como gerar a chave e criptografar o modelo.
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;
}

[NOTA!] Interessado em saber mais sobre Chaves Criptográficas? Consulte a documentação das chaves criptográficas.

Descriptografar o modelo e carregar a partir do fluxo

Antes de carregar o modelo, você precisa descriptografá-lo usando o método CryptographicEngine.Decrypt. CryptographicEngine.Decrypt é um método para desencriptar conteúdo que foi previamente encriptado usando um algoritmo simétrico ou assimétrico. Ao chamar o método, você precisará fornecer a chave gerada anteriormente.

Para acessar o modelo descriptografado, você usará a InMemoryRandomAccessStream classe, que fornece acesso aleatório de dados em fluxos de entrada e saída armazenados na memória em vez de no disco.

Como última etapa, você criará uma sessão para carregar o modelo do fluxo, usando o LearningModel.LoadFromStreamAsync método. Você pode chamar esse método como uma tarefa síncrona ou assíncrona.

O código abaixo mostra como descriptografar o modelo usando a chave gerada, gravá-lo em um fluxo e, em seguida, carregar o modelo do fluxo.

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

Executar o modelo

Copie o seguinte método Run para chamar os métodos definidos anteriormente.

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

Resumo

Está feito! Você carregou com êxito o modelo para seu aplicativo de ML do Windows.

Depois de carregar o modelo, você pode continuar a criar uma sessão, vincular entradas e saídas do modelo e avaliar o modelo para concluir seu aplicativo de ML do Windows.

Recursos adicionais

Para saber mais sobre os tópicos mencionados neste tutorial, visite os seguintes recursos: