paint-brush
Conjuntos de ferramentas FHE de última geração para o multiverso de desenvolvimento: como o TFHE está nos levando até lápor@pascalpaillier
1,095 leituras
1,095 leituras

Conjuntos de ferramentas FHE de última geração para o multiverso de desenvolvimento: como o TFHE está nos levando até lá

por Pascal Paillier23m2024/05/17
Read on Terminal Reader
Read this story w/o Javascript

Muito longo; Para ler

Este artigo explora várias estratégias para projetar a próxima geração de conjuntos de ferramentas FHE apostando no TFHE. O estado atual do conhecimento sobre como instrumentar código homomórfico com TFHE já é suficiente para criar tais ferramentas no presente e disponibilizá-las aos desenvolvedores, permitindo-lhes integrar facilmente a computação confidencial na construção de aplicativos.

People Mentioned

Mention Thumbnail

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coins Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Conjuntos de ferramentas FHE de última geração para o multiverso de desenvolvimento: como o TFHE está nos levando até lá
Pascal Paillier HackerNoon profile picture

Introdução

A FHE está mudando o jogo e estamos todos convidados a jogar.


Se você não tem ideia do que estou falando, significa que ultimamente você tem vivido debaixo de uma rocha. Navegue por alguns dos recursos abrangentes do FHE.org e volte.


Para que a FHE cumpra sua promessa ao mundo da tecnologia, ela deve vir acompanhada de uma nova geração de ferramentas de força industrial para desenvolvimento, compilação e execução em tempo de execução, que qualquer pessoa possa usar para criar aplicativos homomórficos facilmente.


Atualmente, porém, muitos especialistas e empresas no espaço FHE ainda investem a maior parte de seu tempo e esforços na melhoria da criptografia por trás do FHE, em vez de se concentrarem na construção de excelentes ferramentas de desenvolvimento para não especialistas. Ouça-me bem aqui: aprimorar as funcionalidades e o desempenho principais do FHE sempre será uma boa notícia. Mas no grande esquema das coisas, estas melhorias incrementais promovem a adopção global, na melhor das hipóteses, marginalmente. Eles terão impacto na adoção em algum momento, mas não agora .


Do meu ponto de vista, é óbvio que o mundo da tecnologia precisa hoje de cadeias de ferramentas FHE poderosas e fáceis de desenvolver, para começar a desbloquear histórias de sucesso impulsionadas pelo FHE e mover o FHE de uma tendência tecnológica para uma mudança de paradigma real no negócio de segurança digital. Acredito que o estado actual do conhecimento sobre a FHE - tanto científica como tecnologicamente - já é suficiente para construir tais ferramentas no presente e disponibilizá-las às massas conhecedoras de tecnologia sem mais demora. A integração contínua de novos recursos se desenvolverá naturalmente com o tempo, sempre acontece.


Mas o problema é o seguinte: o FHE vem em vários sabores. Dependendo de qual esquema criptográfico você está usando - ou do uso específico que você faz dele, surge uma maneira diferente de representar a computação e executar programas homomórficos. É como se os esquemas FHE fossem animais completamente diferentes, um fornecendo máquinas de Turing e outro cálculo lambda. A biodiversidade é sempre boa em tecnologia ou não, mas também significa que é necessário definir uma estratégia viável ao instrumentar a FHE na prática.


Minha empresa Zama concentra-se em um esquema FHE específico que é o TFHE . TFHE alcança processamento de dados homomórficos com recursos muito específicos: bootstrappings super-rápidos e cálculos expressos como redes de pesquisas de tabela. Adquirimos uma compreensão profunda de como essas peculiaridades - que costumavam fazer do TFHE uma espécie de oprimido no espaço FHE - podem ser traduzidas em bibliotecas homomórficas, compilação, máquinas virtuais ou aceleração de hardware.


Outros concorrentes proeminentes do FHE como CKKS , BGV ou BFV envolvem conceitos muito diferentes em sua instrumentação prática: bootstrappings são muito lentos para serem uma opção, então o processamento é limitado em profundidade, no entanto os dados podem ser vetorizados com lotes massivos, cálculos expressos como circuitos polinomiais e - no caso do CKKS - os resultados são aproximados. Portanto, a tradução de BGV/BFV e CKKS em compiladores e tempos de execução requer uma mentalidade totalmente diferente dos criadores de ferramentas.


No entanto, é improvável que os desenvolvedores se importem muito com qual esquema específico está alimentando seu conjunto de ferramentas e ambientes de tempo de execução FHE, desde que sejam facilmente operados e os requisitos de desempenho sejam atendidos em aplicativos homomórficos implantados. Eles próprios são construtores criativos e seu foco deve estar nas novas experiências que podem oferecer aos seus usuários.


Portanto, o objetivo final dos facilitadores da tecnologia FHE é conceber e fornecer ferramentas que não estejam apenas prontas para seu horário nobre no multiverso de desenvolvimento, mas que sejam fortes o suficiente para estabelecer um novo padrão no setor. Para conseguir isso, eles têm que arriscar sobre qual esquema FHE tem maior probabilidade de levá-los até lá.


Vamos jogar um jogo.


Considere um desenvolvedor que não conhece nada das complexidades do FHE, mas deseja construir um aplicativo homomórfico. Você é o criador da ferramenta aqui, está enfrentando aquele desenvolvedor, de quem pode esperar alguma familiaridade com as práticas comuns de desenvolvimento e os fundamentos da ciência da computação, mas todo o resto - matemática avançada e coisas do gênero, está fora dos limites. Como você pode fazer com que eles produzam o aplicativo FHE por conta própria?


Este artigo explora várias estratégias para ganhar esse jogo apostando no TFHE.


Dependendo da natureza da aplicação – processamento de dados personalizado, redes neurais, contratos inteligentes ou programação de uso geral, serão explorados caminhos vencedores habilitados para TFHE. Esta exploração nos levará por um caminho fácil, um caminho difícil e alguns outros intermediários, com diferentes níveis de prontidão tecnológica na sua realização prática.

O que são programas TFHE?

TFHE significa Toro FHE. Também conhecido como CGGI devido aos nomes de seus descobridores, o TFHE ocupa uma posição única no cenário do FHE: é o mecanismo mais conhecido para permitir o bootstrapping programável (PBS).


Resumindo, um PBS é uma consulta de tabela homomórfica. Ele retorna uma criptografia de T[x] onde T é uma função tabulada de sua escolha, dada uma criptografia de um índice x . Sua velocidade de execução não depende das entradas de T , mas apenas do número de entradas, e está na faixa de milissegundos. Além disso, um PBS redefine o ruído de criptografia incorporado em seu texto cifrado de saída, para que você possa compor PBSs em sequência indefinidamente, sabendo que seu aplicativo homomórfico sempre lidará com textos cifrados limpos.

Redes TFHE

O modelo computacional que o TFHE defende é por excelência.


A unidade elementar de processamento nos programas TFHE se parece exatamente com um neurônio e compõe 2 operações homomórficas básicas:


  1. Uma combinação linear de entradas que retorna E(x) onde x = w_1 x_1 + … + w_n x_n modulo m , dadas as entradas criptografadas E(x_1), …, E(x_n) e um conjunto de pesos de texto simples w_1, …, w_n .


  2. Um PBS que calcula E(T[x]) de E(x) onde T é alguma tabela de texto simples de tamanho m .

Um neurônio TFHE


No "neurônio TFHE", m , x_i , w_i , bem como as entradas T[0], …, T[m-1] são todos inteiros, e pode-se escolher livremente os "parâmetros" m , w_1, …, w_n e T . Dado que a combinação linear tem custo quase zero, o gargalo da eficiência é o PBS cujo tempo de execução depende exclusivamente do módulo m : a velocidade diminui à medida que m aumenta. Isto convida a utilizar valores pequenos - ímpares ou pares, mas pelo menos 2 - para módulos em neurónios TFHE, embora seja necessário encontrar um compromisso para evitar uma redução demasiado drástica da sua expressividade computacional.


Agora, da mesma forma que os neurônios são montados em camadas nas redes neurais para se beneficiar do paralelismo e dos truques de HPC, as redes TFHE acumulam camadas de neurônios TFHE. Cada camada apresenta um módulo de matriz de pesos, um módulo comum m e um vetor de tabelas de pesquisa de tamanho m . No entanto, o módulo pode diferir na camada anterior ou na próxima, assim como o formato da camada.


Uma rede TFHE


E isso encerra o TFHE! Pronto, só precisamos expressar sistematicamente funções como redes de pesquisa. Agora temos nosso modelo computacional homomórfico.


Na realidade, o TFHE suporta múltiplas extensões desse modelo (gráficos arbitrários de operadores de nível inferior, textos cifrados de vários tipos, pesquisas de tabelas com múltiplas saídas, múltiplas formas de empacotar variáveis, etc.). Mas podemos ignorar essas melhorias por enquanto porque a visão de rede de pesquisa já é poderosa o suficiente para nos permitir converter um programa simples em um equivalente homomórfico e executá-lo. Portanto, podemos nos concentrar em como fazer exatamente isso, pelo menos para uma primeira iteração da tecnologia.

Tornando as redes TFHE executáveis

Como tal, uma rede TFHE é apenas um modelo e ainda não está pronta para execução adequada dentro de um aplicativo homomórfico. Embora módulos, matrizes de peso e tabelas de pesquisa sejam totalmente especificados para todas as suas camadas, ainda falta um ingrediente crucial que é uma parametrização criptográfica.


Os parâmetros criptográficos ditam todas as métricas possíveis sobre o que acontecerá dentro da rede em tempo de execução: tamanhos concretos de texto cifrado, as dimensões reais do tensor das chaves de troca de chave e de inicialização internas aos PBSs, várias opções algorítmicas dentro de operadores homomórficos de baixo nível, como as precisões do texto simples e o ruído os níveis evoluem em toda a rede e, em última análise, as especificidades de como criptografar e descriptografar. Eles também prevêem o uso e o desempenho da memória.


Descobrir qual conjunto de parâmetros otimiza a execução de uma rede TFHE pode ser complicado e, em qualquer caso, terrivelmente difícil - mesmo para especialistas - fazer no estilo caneta e papel como nos primeiros dias do FHE, já que tudo depende de tudo . Além disso, vários conjuntos ótimos podem coexistir simultaneamente, exigindo assim uma arbitragem entre o tamanho da chave pública, a latência do caminho crítico ou o rendimento máximo. Felizmente, o problema de automatizar esta tarefa foi resolvido nos últimos anos e agora existem poderosas ferramentas de otimização para determinar rapidamente a melhor instanciação criptográfica de uma determinada rede TFHE.


Parametrização de uma rede TFHE



Uma vez instanciada com parâmetros criptográficos, uma rede TFHE torna-se verdadeiramente executável, ou mais exatamente, é passível de um verdadeiro executável através de uma passagem apropriada de compilação.

Programas TFHE

Um programa TFHE é uma coleção de redes TFHE parametrizadas coladas por "lógica simples".


A lógica pura é feita de


  • instruções operando sobre variáveis de texto simples (ou seja, variáveis normais e não criptografadas),

  • ramificação, incondicional ou condicionada a predicados de texto simples,

  • leitura e escrita de memória em endereços de texto simples, aritmética de ponteiros,

  • chamadas para sub-rotinas/funções.


Basicamente, a lógica simples contém qualquer lógica de programação suportada pela linguagem, com exclusão de um único caso: modificar variáveis criptografadas do programa, que é prerrogativa das partes TFHE do programa. A única coisa que a lógica simples pode fazer com textos cifrados - e também com chaves públicas do TFHE - é movê-los sem alterações e alimentá-los nas partes do TFHE, como se elas estivessem rodando dentro de seu próprio coprocessador ou contêiner separado.


Para todos os efeitos, um programa que atenda a esta definição está completo e pronto para se tornar uma aplicação homomórfica completa, qualquer que seja a linguagem de programação. A compilação personalizada fornecerá esse mapeamento final, e o objeto resultante poderá então ser executado em um tempo de execução habilitado para TFHE ou como um executável independente e independente.


Um programa TFHE


Uma linguagem dedicada pode ser usada para unificar a representação de programas TFHE - como alguns DSL, ou melhor, um dialeto MLIR - para que a compilação possa ser realizada com o mesmo compilador back-end.


A natureza precisa do tempo de execução (biblioteca compartilhada/dinâmica, VM ou outro) é apenas uma modalidade aqui. Qualquer uma das opções levará a um aplicativo homomórfico operacional alimentado por TFHE que pode ser implantado e exposto aos usuários.


Agora vamos voltar ao jogo por um minuto.


Estamos diante de um desenvolvedor que não sabe nada sobre TFHE ou acima, mas deseja construir um aplicativo homomórfico. Suponha que lançamos o compilador discutido acima e o tempo de execução habilitado para TFHE, se houver.


Nosso objetivo está estabelecido, só precisamos de um programa TFHE para chegar a um executável. Mas... como diabos vamos fazer com que o desenvolvedor produza algo tão específico quanto um programa TFHE?

O caminho mais fácil: lançar uma biblioteca FHE e deixar o desenvolvedor fazer o que quer

Aí vem o caminho fácil para vencer: você encapsula toda a complexidade em uma API FHE de caixa preta.

Programas simples

Em qualquer linguagem de programação, um programa (simples) pode ser visto essencialmente como uma combinação de 3 ingredientes:


  • a lógica programática, feita de instruções nativas da linguagem e construções de escopo,

  • variáveis e uma seleção de tipos de dados que o programa lhes atribui, escolhidos entre todos os tipos de dados possíveis,

  • chama uma seleção de funções externas, selecionadas entre todas as funções externas disponíveis, que o programa utiliza para operar em suas variáveis.


Os tipos de dados têm sua própria sublinguagem, uma mistura de tipos nativos e construções de digitação para estender esses tipos nativos e combiná-los em tipos estruturados de nível superior. O sistema de tipos destina-se a fornecer expressividade suficiente para cobrir praticamente qualquer estrutura de dados que o programa possa exigir. Funções externas são aquelas fornecidas por bibliotecas, padrão ou não, mas também podem ser invocadas implicitamente por instruções nativas da linguagem (pense em operadores para aritmética modular ou divisão).


Portanto, programas simples são na verdade "simples":


Um programa simples, em essência


Ouça-me bem aqui. Não estou dizendo que todos os conceitos de programação de alto nível, como polimorfismo, objetos com seus membros e atributos, classes e herança hierárquica, modelos, macros, características, threads, recursão, açúcar sintático, anotações e todos os outros custos zero imagináveis as abstrações fornecidas pela linguagem são necessárias e simples para o desenvolvedor manipular, embora tenham sido inventadas para simplificar seu trabalho.


Só estou dizendo que, para o nosso propósito, eles são apenas decorações inócuas que desaparecem em tempo de compilação, porque uma versão reduzida, porém equivalente, do programa na forma normal é inferida da fonte. Essa versão do programa, expressa em qualquer representação intermediária (IR), é composta de blocos básicos em linha reta - sequências de instruções que são elementares naquela IR - conectados por algum gráfico de fluxo de controle.


Agora é este programa na forma normal que é "simples". Quero dizer, simples o suficiente para ser aumentado com capacidades homomórficas.

Jogue FHE na foto

Você ganha o jogo lançando uma biblioteca FHE nativa do idioma e deixando o desenvolvedor decidir como usá-la da melhor forma.


A biblioteca irá expor novos tipos de dados - criptografados, para complementar os simples - e uma coleção de funções homomórficas que imitam (mais ou menos) as funções simples com as quais o desenvolvedor está familiarizado, só que funcionam com tipos de dados criptografados. Resumindo, você está estendendo o sistema de tipos e o ecossistema da biblioteca e deixando a inteligência do desenvolvedor descobrir como usar essas extensões para criar seu aplicativo homomórfico.


Isto não está particularmente ligado ao TFHE, qualquer esquema FHE servirá. É nisso que os fornecedores das várias bibliotecas FHE se concentram: melhorar a usabilidade e a facilidade de uso do FHE, expondo funções homomórficas de alto nível que parecem o mais próximas possível da experiência de codificação simples. Toda a complexidade criptográfica é abstraída em caixas pretas para as quais o programa fará chamadas oracle.


Isso pode funcionar bem para o desenvolvedor, é claro. Bem... se você cumprir sua parte no acordo como fornecedor da biblioteca.


Eles descobrirão um programa homomórfico que agora se parece com isto.


Um programa homomórfico, em essência


Agora existem variáveis simples e criptografadas coexistentes e o programa precisa manter uma divisão estrita entre esses dois tipos de objetos. Isso ocorre porque existe uma regra de ouro do FHE que diz que quando você aplica uma função a uma mistura de argumentos simples e criptografados, o resultado é necessariamente criptografado, por exemplo, fhe_add(E(x), y) retorna E(x+y) e breve. Portanto, variáveis simples podem entrar em algumas funções FHE, mas nunca sair delas. A criptografia homomórfica “contamina” tudo o que toca por meio da computação.


Então, veja... como você ramifica condicionalmente para uma variável criptografada?


Bem, você não pode. Mas não é um grande problema.

O único soluço: ramificação condicional

Em um aplicativo FHE, a ramificação condicional só pode atuar em booleanos simples, não em booleanos criptografados. Como você saberia para onde pular com base em um bit criptografado? Você não tem a chave privada do usuário para descriptografar esse bit.


Felizmente, o FHE também oferece truques simples para remediar isso.

Como regularizar um if

Suponha que o desenvolvedor inicialmente quisesse fazer algo como


 if (x == 0) then y = 3 else z = 7


mas percebe que, nesse ponto, a variável x estará realmente criptografada. Como adaptar esse pedaço de código?


A primeira coisa a fazer é retrabalhar a instrução if simples para obter uma parte equivalente de código de linha reta que usa multiplexação:


 bit = (x == 0) // bit = 1 if x == 0 otherwise 0 y = 3 * bit + y * (1 - bit) // y = 3 if bit == 1 otherwise no change z = z * bit + 7 * (1 - bit) // z = 7 if bit == 0 otherwise no change


Em uma segunda passagem, o desenvolvedor precisa propagar o fato de que x é do tipo criptografado nas linhas subsequentes:


 bit = fhe_is_equal(x, 0) // bit, y_new and z_new are encrypted y_new = fhe_add(fhe_mul(3, bit), fhe_mul(y, fhe_sub(1, bit))) z_new = fhe_add(fhe_mul(z, bit), fhe_mul(7, fhe_sub(1, bit)))


Pode-se verificar se isso é funcionalmente equivalente à intenção inicial do desenvolvedor e pronto.


Se a linguagem de programação permitir que os operadores nativos sejam sobrecarregados, a API FHE pode até tornar supérfluas as funções explícitas do FHE do segundo trecho, de modo que a primeira reescrita seja a única coisa que o desenvolvedor precisa fazer.


Para dar uma dose extra de açúcar sintático ao desenvolvedor, você pode até expor um operador ternário sobrecarregado a? b : c em que qualquer argumento pode ser criptografado ou não. O trecho de código se torna ainda mais simples:


 bit = (x == 0) // bit = 1 if x == 0 otherwise 0 y_new = bit? 3: y // y = 3 if bit == 1 otherwise no change z_new = bit? z: 7 // z = 7 if bit == 0 otherwise no change


Isso generaliza facilmente para instruções if/switch arbitrárias: toda vez que há uma condição criptografada para verificar, o desenvolvedor só precisa usar a multiplexação para fundir os vários corpos da instrução em um único bloco de código linear equivalente.

Como regularizar um loop for/while

Agora, construções de loop envolvendo condições criptografadas podem ser regularizadas com o mesmo espírito. Tomemos por exemplo


 for (i = 0; i < x; i++) do <body> // i is plain, x is encrypted


onde x deve ser do tipo criptografado. Primeiro, decomponha isso em uma instrução for simples e uma instrução if irregular:


 for (i = 0; i < known_max_value_of_x; i++) do if (i < x) then <body> // i is plain, x is encrypted


e então regularize a instrução if como antes:


 for (i = 0; i < known_max_value_of_x; i++) do bit = (i < x) // i is plain, x and bit are encrypted <new_body> // new body regularized using bit? _ : _


Observe que isso requer um valor known_max_value_of_x . O valor máximo suportado pelo tipo criptografado de x pode ser usado por padrão, mas em muitos casos o desenvolvedor conhece um limite superior muito melhor em x que permite reduzir a contagem total de loops a um mínimo estrito.


No final das contas, as transformações acima são facilmente generalizadas em um método sistemático para regularizar o fluxo de controle irregular, que é fácil para os codificadores assimilarem e adicionarem aos seus hábitos de codificação.

Exemplo: contratos inteligentes confidenciais no EVM

O fhEVM da Zama é uma estrutura de código aberto completa para o desenvolvimento e implantação de contratos inteligentes confidenciais na Máquina Virtual Ethereum (EVM). Os contratos fhEVM são contratos simples do Solidity que são construídos usando conjuntos de ferramentas tradicionais do Solidity. A experiência de desenvolvimento familiar é aumentada pelo FHE pela biblioteca TFHE.sol , que fornece tipos de dados criptografados e substituições FHE para funções padrão.


Os tipos de dados criptografados suportados são atualmente


 ebool, euint4, euint8, euint16, euint32, euint64, eaddress


e inteiros assinados criptografados também serão incluídos em breve. Variáveis criptografadas são criadas a partir de textos cifrados de entrada brutos usando construtores dedicados:


 function mint(bytes calldata encryptedAmount) public onlyContractOwner { euint64 amount = TFHE.asEuint64(encryptedAmount); balances[contractOwner] = balances[contractOwner] + amount; totalSupply = totalSupply + amount; }


Os operadores nativos do Solidity +, -, *, &, |, ^, etc estão sobrecarregados para conveniência do desenvolvedor, e os operadores de comparação fornecidos eq, ne, gt, lt, ge, le retornam um booleano criptografado ebool . O operador ternário homomórfico _? _ : _ é chamado select :


 function bid(bytes calldata encryptedBid) internal { euint32 bid = TFHE.asEuint32(encryptedBid); ebool isAbove = TFHE.le(bid, highestBid); // Replace highest bid highestBid = TFHE.select(isAbove, bid, highestBid); }


No lado do tempo de execução, o fhEVM fornece um EVM habilitado para TFHE onde funções homomórficas são expostas como contratos pré-compilados, o que resulta da integração da biblioteca TFHE-rs Rust de código aberto.


Consulte o white paper do fhEVM para saber mais sobre isso.

O que é necessário para construir uma API FHE com TFHE?

Lembra-se de como são os programas TFHE executáveis, redes TFHE parametrizadas montadas por lógica simples? Bem, você só precisa mapear a lógica do software do desenvolvedor para isso.


O primeiro requisito é ter certeza de que a lógica do programa é “simples”. Isso é exatamente o que ensinamos o desenvolvedor a produzir sozinho, regularizando suas instruções de fluxo de controle. Então, estamos realmente bem nisso agora.


O segundo requisito é que todas as funções homomórficas chamadas pelo programa sejam mapeadas para redes TFHE parametrizadas pré-estabelecidas. Isso é mais complexo do que parece por vários motivos.

1. Você precisa criar redes TFHE para suas funções de API

Pré-estabelecer uma rede TFHE parametrizada que implemente uma determinada função não é necessariamente trivial.


Apenas construir uma adição homomórfica de 2 inteiros não assinados criptografados de 64 bits leva você a muitas opções técnicas: como representar as entradas de 64 bits como vetores de inteiros modulares? Com que módulo (ou múltiplos módulos) exatamente? E então como você realiza um circuito de adição de 64 bits com camadas de pesquisas de tabela?


Muitas opções lá. Mas você acabará se decidindo por meio de uma boa engenharia e conduzindo muitos experimentos.

2. Você precisa normalizar os tipos de dados criptografados

Supondo que você implementou redes TFHE para todas as funções da API, você quer ter certeza de que elas podem ser compostas à vontade, como blocos de Lego.


Isto não é necessariamente garantido porque a melhor forma de representar o mesmo tipo de dados criptografados pode diferir de uma função para outra. Portanto, você precisa adotar um formato aritmético comum para representar cada tipo de dados criptografados, sem incorrer em muita degradação na eficiência de suas redes TFHE.


Novamente, há muitas opções e você precisará arbitrar entre elas.

3. Você precisa garantir a capacidade de composição real

Supondo que todas as redes TFHE sejam agora totalmente compatíveis nos seus formatos de entrada/saída, a capacidade de composição ainda não pode ser garantida.


Isso ocorre porque os parâmetros criptográficos que instanciam uma rede TFHE podem não ser compatíveis com aqueles usados para instanciar outra. Mais particularmente, o nível de ruído de criptografia nos textos cifrados de entrada e saída deve ser ajustado para determinar a capacidade real de composição.


Isso é semelhante à impedância em circuitos eletrônicos; não há como conectar um circuito a outro se houver uma incompatibilidade na impedância. Você precisa primeiro alinhar seus níveis de impedância, e é a mesma coisa aqui. A maneira mais fácil de fazer isso é usar conjuntos fixos de parâmetros - talvez apenas um conjunto único - que são ajustados para garantir o alinhamento em todas as funções da API. Posteriormente, será corrigido o formato das chaves públicas dos usuários, bem como os parâmetros utilizados na criptografia e descriptografia dos usuários, quaisquer que sejam os códigos do desenvolvedor.


Se você encontrar uma maneira de satisfazer esses 3 requisitos ao criar e parametrizar suas redes TFHE, e ainda assim obter um bom desempenho geral, parabéns! Você conseguiu.

Então, por que as bibliotecas FHE não seriam boas o suficiente?

Eles são bons o suficiente para programação de uso geral, assumindo novamente que a API FHE é abrangente o suficiente para fornecer substituições homomórficas para todas as funções padrão que o desenvolvedor espera, com total capacidade de composição.


Mas podem não ser bons o suficiente para programas especializados em


  • funções grandes e com uso intensivo de computação, como no aprendizado de máquina,

  • funções personalizadas e não padrão.


É aí que entra a compilação homomórfica.

O caminho difícil: lançar um compilador homomórfico

O caminho difícil começa aqui: para vencer o jogo fora da programação de uso geral, você agora entregará um compilador TFHE.


O compilador cuidará do que o desenvolvedor não tem ideia de fazer sozinho. Ele será alimentado pela contribuição do desenvolvedor - seja qual for a sua decisão - e terá que completar as partes que faltam para chegar a um programa TFHE.


Vejamos exemplos típicos de aplicativos não padronizados.

Inferência confidencial com redes neurais profundas

Ao transformar uma rede neural simples em um equivalente homomórfico, o desenvolvedor construirá e implantará um serviço de inferência homomórfica em que as entradas e saídas do usuário são criptografadas de ponta a ponta.

O que o desenvolvedor fornece como entrada

Supõe-se que o desenvolvedor conheça o aprendizado de máquina bem o suficiente para produzir um modelo quantizado treinado ou já possua um.


As especificidades de como a quantização é feita realmente importam aqui, já que seu compilador exigirá que o modelo seja basicamente uma rede TFHE - ou que seja facilmente acessível a uma através de uma simples reescrita. Sabe-se que as técnicas de código aberto disponíveis suportam essa forma de quantização, seja pela pós-quantização de um modelo pré-treinado, ou preferencialmente pela realização de Quantization-Aware Training (QAT), que atinge níveis de precisão de última geração em comparação com para modelos não quantizados treinados no mesmo conjunto de dados.


Essencialmente, os módulos usados nas camadas da rede TFHE são potências variáveis de 2, de modo que a precisão dos sinais de ativação é medida em bits. Os pesos são inteiros assinados e as próprias funções de ativação são quantizadas e instanciadas como pesquisas de tabela. Quando as ativações tabulam uma função de sinal rígido deslocada com um deslocamento aprendido, esta definição abrange tipos de modelo como BNNs , TNNs e suas generalizações de vários bits. Mas, em princípio, é possível usar tabelas de pesquisa arbitrárias em funções de ativação e, portanto, elas podem até ser aprendidas durante o treinamento para obter melhores precisões.


O que o desenvolvedor não sabe fazer é converter sua rede TFHE em um executável homomórfico. Portanto, o único ingrediente que falta aqui é apenas uma parametrização criptográfica dessa rede, e isso é tudo que o seu compilador terá que fazer antes de prosseguir para o estágio de compilação back-end.

O que é necessário para parametrizar uma rede TFHE?

Lembre-se que a parametrização de uma rede TFHE fornece uma instanciação criptográfica que pode ser executada. Ele também controla todas as métricas relativas a essa execução, como o tamanho total das chaves públicas do usuário e o tempo total de execução. Portanto, a parametrização é de importância crítica aqui, pois o desenvolvedor procura reduzir a latência de inferência a um mínimo absoluto.


Existem muitos graus de liberdade nos parâmetros criptográficos de uma rede TFHE para forçar todos eles. Além disso, as métricas a serem otimizadas dependem de 2 componentes que são totalmente externos à rede e dependem dos algoritmos que o tempo de execução utiliza para realizar operações TFHE de baixo nível:


  • Uma coleção de fórmulas de ruído . Uma fórmula de ruído relaciona as distribuições de entrada e saída do ruído de criptografia nos pontos finais de um operador, usando os parâmetros do operador como variáveis desconhecidas. Estabelecê-los requer análise científica humana e validação experimental.

  • Uma coleção de métricas de custo . As métricas de custo prevêem a eficiência multidimensional (uso de memória, tempo de execução, etc.) de um operador em função de seus parâmetros. Normalmente são inferidos a partir de medições de referência através de uma análise de melhor ajuste.


Qualquer alteração na implementação do tempo de execução deve ser refletida nestes 2 módulos, pois ambos são fortemente dependentes de algoritmo e de hardware.


As fórmulas de ruído e o modelo de custo do tempo de execução, juntamente com a rede TFHE fornecida, formulam uma instância específica de toda uma classe de problemas de otimização e esta instância é entregue a um otimizador dedicado. Estamos falando de programação não linear inteira mista com múltiplos objetivos aqui, portanto, descobrir uma frente de Pareto de conjuntos ideais de parâmetros requer a solução dessa classe não trivial de problemas de otimização.


Gerando a parametrização ideal de uma rede TFHE

Prontidão tecnológica

A boa ciência e engenharia levaram à resolução deste tipo de problemas de otimização em questão de segundos, e compiladores TFHE como o Concrete já apresentam um eficiente otimizador de parâmetros TFHE como módulo interno.


Várias melhorias podem tornar os otimizadores TFHE ainda mais rápidos no futuro, mas mesmo sem elas, pode-se considerar a parametrização das redes TFHE como - praticamente - um negócio fechado.

Processamento de dados personalizados em alta velocidade

O que o desenvolvedor fornece como entrada

Esses aplicativos são de um tipo totalmente diferente. O desenvolvedor mantém a especificação matemática de uma função personalizada a ser implementada, juntamente com uma restrição de precisão. Tomemos por exemplo

onde x é um número real entre 0 e 1, e usar uma aproximação G de F é aceitável, desde que

O desenvolvedor sabe que implementar G no verso de um envelope, compondo funções de API padrão, provavelmente será muito abaixo do ideal.


O que seu compilador fará é fabricar - dinamicamente - uma nova rede TFHE projetada especificamente para satisfazer a especificação de G . Em seguida, ele irá parametrizá-lo e prosseguir com a compilação back-end para produzir o aplicativo homomórfico.

O que é necessário para sintetizar uma rede TFHE?

Bem, é aí que a estrada de repente se torna muito mais acidentada.

Actualmente, existe uma falta de conhecimento científico sobre como as redes TFHE, com a definição exacta que afirmei anteriormente, podem ser sintetizadas automaticamente. Mesmo as pesquisas sobre a síntese de tipos adjacentes de circuitos que também dependem da aritmética modular de valores inteiros são, na melhor das hipóteses, escassas. Sem falar em qualquer sintetizador pré-existente capaz de realizar esta tarefa de A a Z.

Aproveitando a síntese booleana

Uma maneira de resolver o problema é explorar uma fração do poder computacional das redes TFHE, reduzindo-as a circuitos booleanos. Por exemplo, um neurônio TFHE pode ser forçado a atuar como porta booleana ternária


por

  • definir seu número de entradas para 3 e impor x_1, x_2, x_3 como valores 0/1,
  • definindo seu módulo para m = 4 e seus pesos para (w_1, w_2, w_3) = (2, -1, 1) ,
  • definindo sua tabela de pesquisa como [0, 1, 1, 0] .


Forçando brutalmente todos os pesos e tabelas possíveis com o mesmo módulo, pode-se então constituir um dicionário de neurônios TFHE que pode servir para calcular portas ternárias. O próximo passo consiste em


  • usar uma ferramenta de síntese booleana para gerar um circuito booleano a partir da especificação do desenvolvedor (muitas ferramentas de código aberto estão disponíveis para fazer isso),
  • cortar (também conhecido como particionamento LUT de 3 vias) o circuito em portas ternárias pertencentes ao dicionário,
  • substituindo essas portas ternárias por neurônios equivalentes,
  • remodelar o circuito em uma rede em camadas de profundidade mínima.


Esta é apenas uma estratégia ilustrativa entre muitas porque os métodos que dependem de circuitos booleanos são abundantes. Você também pode considerar apenas as portas binárias usuais e implementá-las com neurônios TFHE restritos. O Cingulata da CEA e - mais tarde - o transpiler FHE do Google foram precisamente os pioneiros nesse caminho com o TFHE.

Prontidão tecnológica

A síntese booleana faz uso de técnicas agressivas de otimização de circuitos e, em geral, é um problema técnico resolvido - ou quase isso, tornando essa abordagem sólida e prática para quem constrói o compilador.


No entanto, uma vez que uma rede TFHE é gerada dessa forma, a sua largura e profundidade podem acabar sendo anormalmente altas, levando a um desempenho geral insatisfatório. Portanto, há uma suspeita generalizada de que, ao relaxar o condicionamento booleano - totalmente artificial - dos neurônios TFHE, pode-se aproveitar toda a sua expressividade e obter redes muito menores e mais superficiais.


Mas, novamente, são necessárias mais pesquisas para identificar claramente como fazer isso. É possível que abordagens totalmente diferentes, como aprender a rede TFHE com algum método de treinamento apropriado emprestado do aprendizado de máquina, acabem fornecendo resultados superiores. O tempo vai dizer.

A busca por um compilador TFHE completo

Supondo que nosso problema de síntese seja resolvido e produza redes TFHE personalizadas eficientes, você estará pronto para juntar todas as peças móveis e projetar um compilador que faça tudo isso:


  1. Seria necessário como entrada um programa simples, onde variáveis sensíveis são simplesmente anotadas como criptografadas.

  2. Aceitaria redes neurais pré-treinadas ou outros modelos de aprendizado de máquina e os reinterpretaria como redes TFHE.

  3. Ele aceitaria modelos de funções feitos apenas de uma especificação matemática e realizaria síntese em tempo real para gerar redes TFHE personalizadas.

  4. Isso transformaria todas as redes TFHE não parametrizadas deixadas na unidade de compilação em instâncias executáveis usando um módulo otimizador sempre que necessário.

  5. Ele executaria o estágio de back-end da compilação para uma variedade de tempos de execução TFHE alvo e/ou arquiteturas de hardware.

  6. Aproveitaria aceleradores de hardware específicos (através do seu modelo de custo) para permitir a síntese e parametrização de redes TFHE mais rápidas.


Inferno, você também pode incluir algum suporte para uma regularização automatizada do fluxo de controle, para que o desenvolvedor nem precise mais se preocupar com isso.


Isso ofereceria aos criadores de aplicativos FHE a melhor experiência de desenvolvimento.

Resumo

No contexto da programação FHE de uso geral, uma biblioteca TFHE pode fornecer modularidade e uma experiência de desenvolvimento totalmente autônoma com conjuntos de ferramentas pré-existentes.


A TFHE é pioneira em técnicas de compilação específicas que podem satisfazer as necessidades do desenvolvedor além desse ponto, mais particularmente para inferência de aprendizado de máquina criptografada e, nos próximos anos, para processamento de dados criptografados em alta velocidade e outras aplicações FHE personalizadas.


No geral, o TFHE fornece um caminho tecnológico claro para criar cadeias de ferramentas FHE mais integradas e adaptáveis que podem se tornar grandes no mundo do desenvolvimento de software e gerar uma nova onda de soluções que priorizam a privacidade, que qualquer um pode construir e executar com uma facilidade sem precedentes.


Ao focar apenas nas redes de pesquisa TFHE, acabei de usar um modelo computacional entre vários que o TFHE pode suportar. À medida que a investigação revela progressivamente mais das suas capacidades, não há dúvida de que novas formas de instrumentar o TFHE surgirão à superfície.


Quais e quando é outra história. Mas por trás dessa história esconde-se uma série de outras questões interessantes e potencialmente esclarecedoras sobre o futuro da computação confidencial.


Créditos ao Midjourney v6, com um pouco de orientação do autor