Python ile Homomorfik Şifreleme
Veri tabanı derslerinde anlatılan normal formlar 90’lı yıllarda disklerin yüksek maliyetli olmaları sebebiyle veri çoklamayı önlemek üzere ortaya atılmış tekniklerdir. Günümüzde özellikle de bulut sistemler hayatımıza girdiğinden beridir verinin saklanması çok ucuzlamıştır. Fakat verinin bize ait olmayan üçüncü parti sistemlerde saklanması sebebiyle verinin güvenliği bugün hiç olmadığı kadar önem kazanmıştır.
Bulutta yer alan bir veri tabanında çalışanlarınızın maaşlarını saklamak istediğinizi varsayalım. Maaş bilgileri bulut sisteme açık olarak gönderilirse ve bulut ortamında şifrelenirse, anahtar bilgisi ele geçirilebileceğinden tüm maaş bilgilerinin çalınması ile karşılaşabiliriz.
Yerel sistemimizde 128 bitlik bir anahtar ürettikten sonra maaş bilgilerinin yine burada şifreleyip buluta şifrelenmiş maaşları gönderirsek çok güvenli bir sistem tasarlamış oluruz. Bulut ortama sızma olsa bile maaş bilgileri şifreli olacağı için bunun kırılması neredeyse imkansızdır.
Ancak bu dizaynda da bir handikap bulunmaktadır. Zam almanız durumunda maaşınızın güncellenmesi için buluttan şifreli maaş bilgisi yerel ortama çekilecek, yerel ortamda bu bilgi deşifrelenecek ve açık maaşınız elde edilecektir. Daha sonra açık maaş bilgisi zaman oranıyla güncellenecek, güncellenmiş maaş aynı anahtar kullanılarak yeniden şifrelenecek ve son olarak da güncellenmiş ve şifrelenmiş maaş bulut ortama aktarılacaktır. Bu tasarımda tüm hesaplama gücü yerel sistemde kullanılmış, bulut sistemin hesaplama gücünden neredeyse faydalanılmamıştır.
Peki daha iyi bir tasarım mümkün müdür?
Homomorfik Şifreleme
Şifreli veriler üzerinde toplama, çarpma gibi matematiksel işlemler yapmamıza izin veren kriptografik özelliklere homomorfik şifreleme diyoruz. Kriptografik algoritmalar toplama ya da çarpma üzerinde homomorfik özellik göstermesi halinde kısmi homomorfik (partially homomorphic), hem toplama hem de çarpma için homomorfik özellik göstermesi halinde de tamamen homomorfik (fully homomorphic) olarak sınıflandırıyoruz.
Homomorfik Algoritmalar
Örneğin RSA çarpımsal homomorfik iken, Paillier, Damgard-Jurik, Okamoto–Uchiyama, Benaloh, Naccache–Stern algoritmaları toplamsal homomorfiktir. Goldwasser–Micali algoritması ise XOR işlemi üzerinde homomorfik özellikler göstermektedir.
İstisna olarak ElGamal algoritması çarpımsal olarak homomorfik iken şifreleme fonksiyonunda yapılan ufak bir modifikasyon ile toplamsal olarak homomorfik hale dönüşmekte ancak çarpımsal olarak homomorfik özelliğini kaybetmektedir. Ayrıca bu modifikasyon kriptosistemin deşifreleme adımında ayrık logaritma probleminin çözümünü ilaveten getirdiğinden majör olarak zorlaştırmaktadır.
Bunun dışında elliptik eğri kriptografisi ve ElGamal kriptosistemlerinin birlikte kullanımı da bize toplamsal homomorfik özellik göstermekte. Ancak modifiye edilmiş ElGamal gibi deşifreleme adımı elliptik eğri ayrık logaritma probleminin çözümünü gerektirdiği için praktikten çok deneysel bir algoritma.
2009 yılında Craig Gentry, Stanford Üniversitesi’de doktora yaparken sunduğu tez çalışmasında tamamen homomorfizmin mümkün olduğunu gösterdiğinden beri Seal, TenSEAL gibi kütüphaneler ile tamamen homomorfik şifreleme pratik olarak hayatımızda yer almakta. Ancak anahtar boyutlarının ve şifreli metinlerin geleneksel açık anahtarlı şifreleme yöntemlerine göre çok çok uzun olması bu yöntemi daha çok deneysel bir yere koymakta.
Dolayısıyla bu yazımızda algoritmaların temellerine girmeden büyük resme odaklanarak kısmi homomorfik şifreleme yöntemleri kullanarak homomorfik şifrelemenin nasıl işlediğini anlatmaya çalışacağız. Prensip olarak aynı kurgu tamamen homomorfik şifreleme yöntemleri ile de uygulanabilir.
Hafif Siklet Kısmi Homomorfik Şifreleme Kütüphanesi
Deneylerimizde Python tabanlı LightPHE kütüphanesini kullanacağız. Kütüphaneyi ilk defa kullanacaksanız Python paket indeks üzerinden aşağıdaki komut ile kütüphaneyi indirebilirsiniz.
1 2 3 4 5 |
!pip install lightphe |
LightPHE kütüphanesi RSA, ElGamal, Exponential ElGamal, Elliptic Curve ElGamal, Paillier, Damgard-Jurik, Okamoto–Uchiyama, Benaloh, Naccache–Stern, Goldwasser–Micali algoritmalarını desteklemektedir. Bu algoritmaların hangi işlemlere göre homomorfik oldukları aşağıdaki tabloda belirtilmiştir.
Kripto Sistemlerin Yaratılması
Bu noktadan sonra ekranı yerel ve bulut sistemimize ait işlemleri ayrı ayrı gerçekleştirmek adına ikiye böleceğiz. Kod parçacıklarının ilk satırlarına onprem.py
ve cloud.py
şeklinde yorum satırları ekleyerek kodun nerede çalıştığını vurgulayacağım.
Yerel sistemde kripto sistemimizi yaratalım. Bu işlem rastgele bir gizli-açık anahtar çifti üretecektir.
1 2 3 4 5 6 |
# onprem.py cs = LightPHE(algoritm_name = "Paillier") |
Gizli anahtara sadece yerel ortamda ihtiyaç duyacağız. Bulut ortamında ise sadece açık anahtar bilgisi olacak. Yerel ortamda aşağıdaki komut ile açık anahtarı dosyaya kaydedeceğiz.
1 2 3 4 5 6 |
# onprem.py cs.export_keys(target_file="public.txt", public = True) |
Bulut ortamında da aynı kripto sistemi sadece açık anahtar bilgisi ile inşa edelim.
1 2 3 4 5 6 |
# cloud.py cs = LightPHE(algoritm_name = "Paillier", key_file = "public.txt") |
Hem yerel hem de bulut ortamında cs.cs.keys
bilgisini basarak yerelde hem gizli ve açık anahtara birlikte sahip olunduğu, bulutta ise sadece açık anahtarın olduğu teyit edilebilir.
Şifreleme
Şifreleme işlemini açık anahtara sahip olan herhangi bir parti gerçekleştirebilir. Hem yerel hem de bulut açık anahtara sahip olduğundan şifrelemeyi iki tarafta da yapabiliriz. Ancak deşifreleme için gizli anahtar gerektirdiğinden sadece yerel ortamda yapılabilecektir.
Örneğin, 10000 USD maaş alan birisinin 2000 USD yıllık zam aldığını varsayalım. Öncelikle bu bilgileri yerel ortamda şifreleyeceğiz.
1 2 3 4 5 6 7 8 9 10 |
# onprem.py m1 = 10000 # maas m2 = 2000 # zam c1 = cs.encrypt(m1).value c2 = cs.encrypt(m2).value |
c1
ve c2
şifreli verileri yerel ortamdan buluta gönderilir.
1 2 3 4 5 6 7 |
# cloud.py c1 = cs.create_ciphertext_obj(c1) c2 = cs.create_ciphertext_obj(c2) |
Bulut ortamda gizli anahtar olmadığı için eğer c1, c2
çiftini deşifrelemek istersek aşağıdaki gibi hata alacağız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# cloud.py pytest.raises( ValueError, match="You must have private key to perform decryption" ): cs.decrypt(c1) pytest.raises( ValueError, match="You must have private key to perform decryption" ): cs.decrypt(c2) |
Öte yandan, yerel tarafta gizli anahtar olduğu için deşifreleme işlemini gerçekleştirebilmekteyiz.
1 2 3 4 5 6 7 |
# onprem.py assert cs.decrypt(c1) == m1 assert cs.decrypt(c2) == m2 |
Homomorfik Toplama
Paillier kripto sistemi toplamsal olarak homomorfikti. Dolayısıyla bulut tarafındaki şifreli c1 - c2
verileri üzerinde toplama işlemi gerçekleştirebiliriz.
1 2 3 4 5 6 7 |
# cloud.py c3 = c1 + c2 c3 = c3.value |
Şimdi de bulut sistemde hesaplanan c3
değerini yerel sisteme gönderelim. c3
‘ü c1
ve c2
‘nin toplamı olarak hesaplamıştık. Dolayısıyla c3
‘ü deşifrelersek, m1
ve m2
mesajlarının toplamını elde etmiş olacağız.
1 2 3 4 5 6 7 |
# onprem.py c3 = cs.create_ciphertext_obj(c3) assert cs.decrypt(c3) == m1 + m2 |
Gördüğünüz üzere, c3
‘ün hesaplanması bulut sistemde şifreli c1
ve c2
verilerinin toplanmasıyla elde edildi. Bunu deşifrelediğimiz zaman, m1
ve m2
mesajlarının toplamını elde ediyoruz. Bu hesaplama sırasında tüm hesaplama gücü gördüğünüz gibi bulut sistemde kullanıldı!
Homomorfik Çarpma
Paillier toplamsal olarak homomorfikti ancak çarpımsal olarak homomorfik değildi. Eğer bulut sistemde iki şifreli veriyi çarpmaya çalışırsak, kütüphane bize Paillier ile bu işlemin yapılamadığına dair bir hata verecektir.
1 2 3 4 5 6 7 8 9 10 |
# cloud.py pytest.raises( ValueError, match="Paillier is not homomorphic with respect to the multiplication" ): c1 * c2 |
Eğer kripto sistemi Paillier yerine RSA veya ElGamal ile inşa etmiş olsaydık, homomorfik çarpma yapabilecekken bu seferde homomorfik toplama yapamayacaktık.
Skaler Çarpma
Her ne kadar Paillier çarpımsal olarak homomorfik olmasa da, şifreli metni bir sabit ile çarpma işlemini destekliyor. Örneğin, c1
şifreli verisini 1.05 ile çarpalım. Bir şeyi 1.05 ile çarpmak, onun değerini %5 artırmak anlamına geliyor.
1 2 3 4 5 6 7 |
# cloud.py c4 = c1 * 1.05 c4 = c4.value |
c4
şifreli verisini yerel ortama gönderdiğimizde, bunu deşifrelediğimiz zaman m1
mesajının %5 fazlasını elde ettiğimizi aşağıdaki kod bloğu ile teyit etmiş oluyoruz.
1 2 3 4 5 6 7 |
# onprem.py c4 = cs.create_ciphertext_obj(c4) assert cs.decrypt(c4) == m1 * 1.05 |
Sonuç
Bu yazıda mevcut simetrik şifreleme yöntemleri ile tasarlanacak sistemlerin eksikliklerini ve bunlar yerine homomorfik şifreleme yöntemleri kullanılırsa ne gibi kazanımlar sağlayabileceğimizi göstermeye çalıştık. Bunu yaparken Python tabanlı LightPHE kütüphanesini kullandık ve deneylerimizde Paillier kripto sistemini benimsedik. Ancak LightPHE, Paillier dışında RSA, ElGamal, Exponential ElGamal, Elliptic Curve ElGamal, Damgard-Jurik, Okamoto–Uchiyama, Benaloh, Naccache–Stern ve Goldwasser–Micali algoritmalarını desteklediği için sizler deneylerinizde bu algoritmaları kullanmayı deneyebilirsiniz.
Kütüphanenin repo adresi https://github.com/serengil/lightphe üzerinden yıldız vererek bu çalışmaya destek olabilirsiniz.