Une forme de cryptage qui permet le calcul sur des textes chiffrés générant un résultat crypté qui, une fois décrypté, correspond au résultat des opérations comme si elles avaient été effectuées sur du texte en clair. — Massimo Bertaccini ( )
Utilisez un homomorphisme de confidentialité spécial pour crypter ses données afin que l'ordinateur en temps partagé puisse fonctionner sur les données sans qu'il soit nécessaire de les décrypter au préalable.
En d'autres termes, je souhaite supprimer le traitement de mes données sans en céder l' accès .
Pour le dire autrement encore, function(A, B) = function (A , B
) où A and B
sont des valeurs chiffrées de A et B, respectivement. Cela permet à des tiers de calculer des données cryptées et de fournir les résultats sans avoir aucune connaissance de la valeur d'origine. Avec RSA, deux valeurs chiffrées avec la même clé peuvent être multipliées et le produit peut être déchiffré pour donner le produit des valeurs chiffrées.
Une bibliothèque | Régimes | Langue | Licence |
---|---|---|---|
BFV, BGV, CKKS | Wrapper C++/C# | MIT | |
Ouvrir FHE | BFV, BGV, CKKS, DM, CGGI | C++ | Licence BSD à 2 clauses |
CKKS | C++ | Creative Commons 3.0 | |
TFHE (Tore) | Rouiller | BSD-3-Clause-Effacer | |
TFHE | Rouiller | BSD-3-Clause-Effacer | |
BFV, BGV, CKKS | Va | Apache 2.0 | |
N/A – Utilise SEAL, PALISADE, HLib | Python, Docker | Apache 2.0 |
Pour commencer, une clé publique est créée par le client et partagée avec le serveur. Il est utilisé pour chiffrer des données et également pour effectuer des opérations arithmétiques sur des données chiffrées. Le client et le serveur utilisent tous deux un Encryptor. Le client génère et conserve une clé privée utilisée pour le déchiffrement utilisé par le bien nommé 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);
Les clés de relinéarisation sont transmises du client au serveur. Selon Microsoft SEAL, ils n'ont aucune signification sémantique autre que de réduire la taille du Ciphertext suite à une opération de multiplication.
Sur la ligne de commande, l'utilisateur entre le temps et la distance.
Chaque valeur est encodée en PlainText, puis chiffrée en Ciphertext et enfin encodée en base64 avant de l'envoyer au serveur.
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);
Le serveur exécute une fonction d'amorçage similaire en créant un SEALContext en utilisant uniquement la clé publique et les clés de relinéarisation, puis traite la requête :
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));
L'inverse du temps est utilisé pour calculer la vitesse de l'exécution soumise et la méthode RelinearizeInplace réduit la taille du texte chiffré résultant . La distance, le temps et la vitesse sont enregistrés dans une liste en mémoire.
La méthode GetMetrics agrège la liste et renvoie :
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; . . . }
Étant donné que le serveur conserve une trace du nombre de soumissions d'exécutions, le nombre total d'exécutions n'est pas une valeur chiffrée. Cette valeur non chiffrée peut être convertie en texte brut et utilisée dans une opération effectuée sur le texte chiffré. Bien qu'il s'agisse d'un exemple simple, les implications méritent d'être notées. Le serveur peut fournir des valeurs supplémentaires utilisées sur les données cryptées permettant aux fournisseurs tiers d'appliquer des données exclusives aux calculs par rapport aux données cryptées fournies par le client.
Dans l'exemple ci-dessous, le nombre total est converti en réciproque et ajouté à une List<double>. Les opérations CKKS attendent des valeurs de liste chiffrées, même si la liste ne contient qu'une seule valeur. Ainsi, le List<double> est encodé en un PlainText . MultiplyPlainInplace multiplie totalSpeed par (1/nombre d'exécutions), ce qui donne la vitesse moyenne. Pour économiser de l'espace, le résultat est appliqué au texte chiffré totalSpeed et les clés de relinéarisation réduisent la taille de la sortie.
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);
Les valeurs sont encodées en base64, renvoyées et déchiffrées sur le client. Le client prend l'étape supplémentaire de convertir le texte brut déchiffré en 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);
Milles | Temps |
---|---|
2.5 | 0:35:32.643 |
2.2 | 0:32:48.826 |
2.8 | 0:34:52.036 |
Microsoft SEAL est un projet Microsoft Research et n'est pas prêt pour une application de production. Toutes les classes implémentent IDisposable et utilisent des ressources non managées. Le code de production devrait se protéger contre une fuite de mémoire. La classe SEALContext ne respecte pas le principe de responsabilité unique. Il comprend des méthodes pour BGV/BVF et CKKS. De plus, CKKS prend en charge les opérations vectorielles, mais pas l'addition de vecteurs. Une seule List<double> peut être chiffrée en un seul CipherText mais il n'y a aucun moyen de sommer les valeurs dans un seul CipherText. Cela peut être fait avec , mais c'est une solution sous-optimale.