Uma forma de criptografia que permite a computação em textos cifrados gerando um resultado criptografado que, quando descriptografado, corresponde ao resultado das operações como se tivessem sido executadas em texto simples. — Massimo Bertaccini ( )
Use um homomorfismo de privacidade especial para criptografar seus dados para que o computador de time-share possa operar nos dados sem a necessidade de descriptografá-los primeiro.
Em outras palavras, desejo excluir o processamento dos meus dados sem ceder o acesso a eles.
Em outras palavras, function(A, B) = function (A , B
) onde A and B
são valores criptografados de A e B, respectivamente. Isso permite que terceiros calculem dados criptografados e forneçam os resultados sem ter conhecimento do valor original. Com o RSA, dois valores criptografados com a mesma chave podem ser multiplicados e o produto pode ser descriptografado gerando o produto dos valores criptografados.
Biblioteca | Esquemas | Linguagem | Licença |
---|---|---|---|
BFV, BGV, CKKS | C++/C# Wrapper | MIT | |
Abrir FHE | BFV, BGV, CKKS, DM, CGGI | C++ | Licença de 2 Cláusulas BSD |
CKKS | C++ | Creative Commons 3.0 | |
TFHE (Toro) | Ferrugem | BSD-3-Clause-Clear | |
TFHE | Ferrugem | BSD-3-Clause-Clear | |
BFV, BGV, CKKS | Vai | Apache 2.0 | |
N/A – Usa SEAL, PALISADE, HLib | Python,Docker | Apache 2.0 |
Para começar, uma chave pública é criada pelo cliente e compartilhada com o servidor. Ele é usado para criptografar dados e também para executar operações aritméticas em dados criptografados. Tanto o cliente quanto o servidor usam um Encryptor. O cliente gera e retém uma chave privada usada para descriptografia usada pelo apropriadamente chamado Decryptor .
using Microsoft.Research.SEAL; protected SEALContext _context; private KeyGenerator _keyGenerator; private Encryptor _encryptor; private Decryptor _decryptor; protected IFitnessTrackerApiClient _apiClient; . . . _context = SEALUtils.GetContext(_config.Value.PolyModulusDegree, this.SchemeType); _keyGenerator = new KeyGenerator(_context); _keyGenerator.CreatePublicKey(out PublicKey publicKey); _keyGenerator.CreateRelinKeys(out RelinKeys relinKeys); _encryptor = new Encryptor(_context, _publicKey); _decryptor = new Decryptor(_context, _keyGenerator.SecretKey); . . . PublicKeyModelCKKS keyModelCKKS = new( SEALUtils.KeyToBase64String(_publicKey), SEALUtils.KeyToBase64String(relinKeys)); await _apiClient.SendPublicKeyCKKSAsync(keyModelCKKS);
As chaves de relinearização são passadas do cliente para o servidor. De acordo com o Microsoft SEAL, eles não têm nenhum significado semântico além de reduzir o tamanho do texto cifrado após uma operação de multiplicação.
Na linha de comando, o usuário insere o tempo e a distância.
Cada valor é codificado para PlainText, depois criptografado para Ciphertext e finalmente codificado para base64 antes de enviá-lo ao servidor.
using Microsoft.Research.SEAL; var plaintext = new Plaintext(); _encoder.Encode(value, _scale, plaintext); var ciphertext = new Ciphertext(); _encryptor.Encrypt(value, ciphertext); using (var ms = new MemoryStream()) { ciphertext.Save(ms); return Convert.ToBase64String(ms.ToArray()); }
RunItemCKKS metricsRequest = new( EncryptBase64(runItem.Distance), EncryptBase64(runItem.Time), EncryptBase64(1 / runItem.Time)); await _apiClient.AddNewRunningDistanceCKKSAsync(metricsRequest);
O servidor executa uma função de inicialização semelhante criando um SEALContext usando apenas a chave pública e as chaves de relinearização e, em seguida, processa a solicitação:
var distance = SEALUtils.BuildCiphertextFromBase64String(request.Distance, _sealContext); var time = SEALUtils.BuildCiphertextFromBase64String(request.Time, _sealContext); var timeReciprocal = SEALUtils.BuildCiphertextFromBase64String(request.TimeReciprocal, _sealContext); Ciphertext speed = new(); _evaluator.Multiply(distance, timeReciprocal, speed); _evaluator.RelinearizeInplace(speed, _relinKeys); _runListCKKS.Add(new EncryptedRunInfoCKKS(distance, time, speed));
Um recíproco do tempo é usado para calcular a velocidade da execução enviada e o método RelinearizeInplace reduz o tamanho do texto cifrado resultante . Distância, tempo e velocidade são salvos em uma lista na memória.
O método GetMetrics agrega a lista e retorna:
public SummaryItemCKKS GetMetrics() { int count = _runListCKKS.Count; var totalDistanceCKKS = SumEncryptedValues(_runListCKKS.Select(m => m.Distance)); var totalTimeCKKS = SumEncryptedValues(_runListCKKS.Select(m => m.Time)); var totalSpeed = SumEncryptedValues(_runListCKKS.Select(m => m.Speed)); . . . protected Ciphertext SumEncryptedValues(IEnumerable<Ciphertext> encryptedData) { . . . Ciphertext encTotal = new(); _evaluator.AddMany(encryptedData, encTotal); return encTotal; . . . }
Como o servidor controla o número de envios de execução, o número total de execuções não é um valor criptografado. Esse valor não criptografado pode ser convertido em texto simples e usado em uma operação executada em texto cifrado. Embora este seja um exemplo simples, vale a pena observar as implicações. O servidor pode fornecer valores adicionais usados em dados criptografados, permitindo que provedores terceirizados apliquem dados proprietários a cálculos contra dados criptografados fornecidos pelo cliente.
No exemplo abaixo, a contagem total é convertida em um recíproco e adicionada a uma List<double>. As operações CKKS esperam valores de lista criptografados, mesmo que a lista contenha apenas um único valor. Assim, o List<double> é codificado para um PlainText . O MultiplyPlainInplace multiplica totalSpeed por (1/número de execuções), resultando na velocidade média. Para economizar espaço, o resultado é aplicado ao totalSpeed Ciphertext e as chaves de relinearização reduzem o tamanho da saída.
Plaintext encodedCountReciprocal = new(); List<double> averagePaceList = new(); double runCountReciprocal = 1 / (double)count; averagePaceList.Add(runCountReciprocal); _encoder.Encode(averagePaceList, _scale, encodedCountReciprocal); _evaluator.MultiplyPlainInplace(totalSpeed, encodedCountReciprocal); _evaluator.RelinearizeInplace(totalSpeed, _relinKeys);
Os valores são codificados em base64, retornados e descriptografados no cliente. O cliente executa a etapa adicional de converter o texto simples descriptografado em List<double> .
var payload = Convert.FromBase64String(encryptedDistanceText); using var ms = new MemoryStream(payload); var ciphertext = new Ciphertext(); ciphertext.Load(_context, ms); var decryptedText = new Plaintext(); _decryptor.Decrypt(cypherText, decryptedText); List<double> distanceList = new(); _encoder.Decode(decryptedText, distanceList);
milhas | Tempo |
---|---|
2.5 | 0:35:32.643 |
2.2 | 0:32:48.826 |
2.8 | 0:34:52.036 |
O Microsoft SEAL é um projeto da Microsoft Research e não está pronto para um aplicativo de produção. Todas as classes implementam IDisposable e usaram recursos não gerenciados. O código de produção precisaria proteger contra um vazamento de memória. A classe SEALContext não segue o princípio de responsabilidade única. Inclui métodos para BGV/BVF e CKKS. Além disso, CKKS suporta operações vetoriais, mas não adição vetorial. Uma única List<double> pode ser criptografada em um único CipherText , mas não há como somar os valores em um único CipherText. Isso pode ser feito com , mas essa é uma solução abaixo do ideal.