Tam Değil Ama Yeterli: Somewhat Homomorphic Encryption
Günümüzde veri gizliliği, özellikle bulut bilişim ve dağıtık sistemlerin yaygınlaşmasıyla birlikte her zamankinden daha kritik bir hâle geldi. Hassas verilerin üçüncü taraf sistemlerde işlenmesi gerekliliği, “veriyi açmadan işlem yapabilir miyiz?” sorusunu da beraberinde getiriyor. Bu soruya kriptografi dünyasının verdiği en güçlü yanıtlardan biri homomorfik şifreleme yaklaşımıdır. Temel olarak üç farklı seviyede karşımıza çıkar: yalnızca tek bir işlem türünü destekleyen partially homomorphic encryption (kismi homomorfik), sınırlı sayıda ve derinlikte işlemlere izin veren somewhat homomorphic encryption (sınırlı homomorfik şifreleme) ve teorik olarak herhangi bir hesaplamayı şifreli veri üzerinde gerçekleştirebilen fully homomorphic encryption (tamamen homomorfik). Bu yazıda odağımız somewhat homomorphic encryption olacak; ancak önce bu üç yaklaşım arasındaki farkları kısaca netleştirip, ardından somewhat yaklaşımının neleri mümkün kıldığını ve hangi noktalarda yetersiz kaldığını inceleyeceğiz. Sınırlı homomorfik şifreleme, kısmi homomorfikten daha kuvvetliyken, tamamen homomorfikten daha zayıf şekilde sınıflandırabiliriz.

Kısmi Homomorfik Şifreleme (Partially Homomorphic Encryption)
Önce RSA ile partially homomorphic özelliği gösterelim:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
from lightphe import LightPHE # build a rsa cryptosystem cs = LightPHE(algorithm_name="RSA") # define plaintexts m1 = 17; m2 = 23 # encrypt plaintexts c1 = cs.encrypt(m1) c2 = cs.encrypt(m2) # homomorphic operation c3 = c1 * c2 # proof of work assert cs.decrypt(c3) == m1 * m2 |
Fakat RSA ile ciphertext’ler üzerinde toplama yapılmaya çalışılırsa aşağıdaki şekilde hata alınacaktır:
|
1 2 3 4 5 6 |
with pytest.raises(ValueError, match = "RSA is not homomorphic with respect to the addition"): _ = c1 + c2 |
RSA yerine Paillier kriptosistemini kullanırsak bu sefer toplama yapabiliriz ama çarpma yapamayız:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# build a paillier cryptosystem cs = LightPHE(algorithm_name="Paillier") # define plaintexts m1 = 17; m2 = 23 # encrypt plaintexts c1 = cs.encrypt(m1) c2 = cs.encrypt(m2) # homomorphic operation c3 = c1 + c2 # proof of work assert cs.decrypt(c3) == m1 + m2 with pytest.raises(ValueError, match = "Paillier is not homomorphic with respect to the multiplication"): _ = c1 * c2 |
Sınırlı Homomorfik Şifreleme (Somewhat Homomorphic)
Sınırlı homomorfik şifreleme algoritması olan Boneh-Goh-Nissim ya da kısaca BGN ile hem toplama hem de çarpma yapabiliyoruz:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# build a bgn cryptosystem cs = LightPHE(algorithm_name="Boneh-Goh-Nissim", key_size=50) # define plaintexts m1 = 17; m2 = 23 # encrypt plaintexts c1 = cs.encrypt(m1) c2 = cs.encrypt(m2) # homomorphic operations c3 = c1 + c2 c4 = c1 * c2 # proof of work assert cs.decrypt(c3) == m1 + m2 assert cs.decrypt(c4) == m1 * m2 |
Peki hem toplama hem de çarpma yapabiliyorsak neden tamamen homomorfik (fully homomorphic) değil de sınırlı homomorfik? Çünkü BGN ile sınırsız sayıda toplama yapabiliyoruz ama çarpma işlemi yalnızca bir kez yapılabiliyor.
|
1 2 3 4 5 6 7 |
with pytest.raises(ValueError, match="Boneh-Goh-Nissim only supports multiplication ciphertexts once!"): # c4 was c1 * c2 _ = c4 * c1 |
Bunun sebebi, BGN algoritmasının eliptik eğrileri kullanmasıdır ve toplama işlemi aslında eğri üzerindeki nokta toplamaya denk gelmektedir. Ancak eliptik eğriler üzerinde iki noktanın çarpılması işlemi tanımlı değildir. Yalnızca grup toplamı (iki noktanın toplanması) ve skalar çarpım (bir noktanın skalar bir değerle çarpılması) vardır. Bunun için eliptik eğri eşlemesi (pairing) kullanırız. Yani çalıştığımız uzayı eliptik eğri grubu olan G’den G_T’ye taşırız. Çarpma ile uzay bir kere G_T’ye taşındığında, bir daha çarpma yapılamamasının nedeni de tekrar G_T’ye taşınamayacak olmasıdır.

Yine de çarpma ile G_T uzayına geçtikten sonra bu uzaydaki elemanları kendi aralarında toplayabiliriz. Yani çarpma sonrası toplama geçerli bir işlemdir. Peki çok sayıda çarpımın kendi arasında toplanması işlemini nerede kullanıyoruz?
Lineer Regresyon
Lineer regresyon denklemini hatırlarsak:
y = Σ xi wi
Girdiler kendi ağırlıkları ile çarpılır ve bu çarpımlar kendi aralarında toplanır. Aşağıdaki şekilde hem girdileri hem ağırlıkları BGN kriptosistemi ile şifreledikten sonra ciphertext’ler kendi aralarında toplanırsa lineer regresyon sonucunu şifreli olarak elde ederiz.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
cs = LightPHE( algorithm_name="Boneh-Goh-Nissim", key_size=50, ) # Feature values x1 = 5 x2 = 3 # Model weights w1 = 7 w2 = 4 # Encrypt values x1_enc = cs.encrypt(plaintext=x1) w1_enc = cs.encrypt(plaintext=w1) x2_enc = cs.encrypt(plaintext=x2) w2_enc = cs.encrypt(plaintext=w2) # Homomorphic multiplications (feature × weight) x1w1_enc = x1_enc * w1_enc x2w2_enc = x2_enc * w2_enc # Homomorphic addition (sum of contributions) sum_enc = x1w1_enc + x2w2_enc # Decrypt final result sum_decrypted = cs.decrypt(sum_enc) assert sum_decrypted == (x1 * w1 + x2 * w2) |
Kosinüs Benzerliği
Eğer kaynak ve hedef vektörleri L2 normalize durumda ise dot product işlemi kosinüs benzerliği verir:
v1 · v2 = Σ xi wi
Vektörün her boyutuna ait değeri BGN ile şifreledikten sonra aynı sıraya ait şifreli boyutlar kendi aralarında çarpılır ve bu çarpımlar kendi aralarında toplanırsa şifreli kosinüs benzerliğini hesap etmiş oluruz. Lineer regresyon implementasyonunda uyguladığımız kodu bire bir dot product ya da kosinüs benzerliği için kullanabiliriz.
Kısmi homomorfik şifreleme algoritmaları ile dot product hesabını kaynak ya da hedef vektörden biri plain durumdaysa toplamsal homomorfik algoritmalar ile gerçekleştirebiliyorduk. Bunu yaparken çarpım için toplamsal homomorfik algoritmaların skalar çarpma özelliğini kullandıktan sonra kendi aralarında toplama yapıyorduk. BGN ile kaynak ve hedef vektörlerin her ikisi de şifreli iken veya yine biri şifreli biri plain durumdaysa da bu işlem yapılabilmektedir.
Öklid Uzaklığı
Öklid uzaklığı formülünün sağ tarafında normalde karekök vardır:
d(v1, v2) = √(xi – yi)²
Öklid uzaklığının karesini hesaplamak istersek sağ taraftaki karekökten kurtuluruz:
d(v1, v2)² = Σ (xi – yi)²
Tabii karar alma adımında Öklid uzaklığı bir eşik değerden büyük mü küçük mü kontrolü yerine, Öklid uzaklığının karesi eşik değerinin karesinden büyük mü küçük mü diye kontrol edeceğiz.
Bu işlemdeki ikinci püf nokta, vektörlerden birini negatif değerleri ile şifrelemek olacaktır. Çünkü homomorfik olarak çıkarma işlemi tanımlı değildir; ancak sadece toplama kullanabiliyoruz. Çiftin biri negatif değerli ise toplamanın dağılım özelliğinde çıkarma sonucunu elde edebiliriz.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
cs = LightPHE(algorithm_name="Boneh-Goh-Nissim", key_size=50) # v1 = [5, 2, 8] i1, i2, i3 = 5, 2, 8 # v2 = [1, 1, 2] j1, j2, j3 = 1, 1, 2 # Encrypt v1 i1_enc = cs.encrypt(i1) i2_enc = cs.encrypt(i2) i3_enc = cs.encrypt(i3) # Encrypt negative v2 (to simulate subtraction) j1_enc = cs.encrypt(-j1) j2_enc = cs.encrypt(-j2) j3_enc = cs.encrypt(-j3) # Compute squared Euclidean distance euclidean_sqrt_enc = ( (i1_enc + j1_enc) * (i1_enc + j1_enc) + (i2_enc + j2_enc) * (i2_enc + j2_enc) + (i3_enc + j3_enc) * (i3_enc + j3_enc) ) assert ( cs.decrypt(euclidean_sqrt_enc) == (i1 - j1) ** 2 + (i2 - j2) ** 2 + (i3 - j3) ** 2 ) |
Peki sınırlı homomorfik şifreleme ile ne yapamayız?
Lineer regresyonu modelleyebilmiştik ama lojistik regresyonu, Euler sayısının üssü şeklinde hesaplama gerektirdiği için yapamayız. Ya da deep neural networks hesabı BGN ile yapılamaz.
Yine de kısmi ve sınırlı homomorfik şifreleme algoritmaları, tamamen homomorfik algoritmalara göre daha kısa anahtar boyutu ve daha hızlı işlem süreleri ile geldiğinden, bu işlem setleri için tamamen homomorfik algoritmaları kullanmamız her zaman gerekmiyor.
Özet ve Sonuç
Bu yazıda homomorfik şifrelemenin farklı seviyelerini—partially, somewhat ve fully homomorphic encryption—birbirleriyle karşılaştırarak ele aldık ve özellikle somewhat homomorphic encryption yaklaşımını Boneh–Goh–Nissim (BGN) üzerinden inceledik. RSA ve Paillier gibi kısmi homomorfik sistemlerin yalnızca tek bir işlem türüne izin verdiğini, buna karşın BGN’nin hem toplama hem de sınırlı çarpma desteği sunarak daha geniş bir hesaplama alanı açtığını gördük.
Ancak bu esnekliğin bir bedeli var: işlem derinliği kısıtları. BGN gibi somewhat homomorphic sistemlerde çarpma işlemi sınırlı sayıda yapılabilirken, toplama işlemi çok daha serbesttir. Bu durum, özellikle lineer regresyon, dot product, kosinüs benzerliği ve Öklid uzaklığı gibi lineer cebire dayalı problemlerde güçlü kullanım senaryoları oluşturur. Buna karşılık, lojistik regresyon veya derin sinir ağları gibi yüksek dereceli non-lineer hesaplamalar için bu sistemler yetersiz kalır ve fully homomorphic encryption ihtiyacı ortaya çıkar.
Öte yandan, fully homomorphic encryption sistemlerinin sağladığı evrensellik, beraberinde yüksek hesaplama maliyeti ve büyük anahtar boyutları gibi pratik zorlukları da getirir. Bu nedenle birçok gerçek dünya uygulamasında, “tam homomorfik” yerine “yeterince homomorfik” sistemler daha verimli ve uygulanabilir bir denge sunar.
Sonuç olarak, homomorfik şifreleme bir spektrum olarak düşünüldüğünde, her seviyenin kendine özgü bir kullanım alanı vardır. Hangi yaklaşımın seçileceği ise tamamen problemin hesaplama derinliğine, performans gereksinimlerine ve gizlilik ihtiyaçlarına bağlıdır.
Eğer bu yazı hoşunuza gittiyse LightPHE reposuna GitHub’ta yıldız verebilirsiniz, bu projenin daha çok kişiye ulaşmasına yardımcı oluyor. Destekleriniz için şimdiden teşekkürler!