
Bu eğitimde, ZK tabanlı özel bir oylama sistemi olan Privote'u uyguluyoruz; bu sistemde oylama sona erene kadar seçmenların tercihleri kimse tarafından görülemez.

Kayıtlı bir seçmen olarak belirli bir konu veya aday üzerinde oy kullandığınızı hayal edin. Harici bir taraf oyunuzu satmanızı istiyor; başka bir deyişle, bazı teşvikler karşılığında kendi tercihiniz yerine onların tercihine oy vermenizi talep ediyor. Bu talebe boyun eğerseniz, genellikle bir blockchain işlem makbuzu aracılığıyla oyunuzun kanıtını sunmanız gerekecek. Oyunuzu satmaya meyilliyseniz bu kulağa cazip bir fırsat gibi gelebilir; ancak bu durum tüm oy verme sürecinin bütünlüğünü zedeler.
Seçmenlerin tercih ettikleri aday veya konular için oy kullanmasını sağlarken seçimlerini gizleyerek başkalarının görmesini nasıl engelleyebiliriz? Yanıt tek bir kelimede gizli: Şifreleme.
Bu eğitimde, blockchain üzerinde şifrelemeyi kullanan basit bir oylama uygulaması olan Privote'u nasıl geliştireceğimizi inceleyeceğiz. Zamanı geldiğinde oylar şifresi çözülerek sayılır ve sonuçlar seçmenlerin anonimliği korunarak blockchain'e geri yayımlanır. Sonuçlar, sıfır bilgi (ZK) kanıtı aracılığıyla doğrulanır. Mükemmel olmasa da bu örnek, temel kavramları açıkça ortaya koymaktadır.
Blockchain oylamasını derinlemesine anlamak için lütfen Vitalik Buterin'in blog yazısına başvurun.
Devam etmeden önce, Privote dapp'inin ana bileşenlerine ilişkin bir özet sunalım:
Akıllı Sözleşme: Bu sistem, birden fazla oyu (oy pusulasını) ve başlıklar, mevcut seçenekler ile şifrelenmiş veriler gibi ilgili bilgileri depolar.
Güvenilir Taraf: Oyları şifreleyen, sonuçları hesaplayan ve bunları blockchain'de yayımlayan zincir dışı bir sunucu. Bu sunucuya "Güvenilir Taraf" denmesinin bir nedeni vardır: Yanlış hesaplama yaparak ya da mesajları sansürleyerek hatalı sonuçlar yayımlayamaz.
Frontend: Kullanıcıların cüzdanlarını bağladığı ve oy gönderdiği bir platform. "Yönetici"nin kullanılan oy sayısını görüntüleyip sonuçları manuel olarak yayımlayabileceği ayrı bir sayfa da bulunacaktır.
Privote'u başarıyla oluşturmak için iki zorluğun üstesinden gelmemiz gerekiyor:
Herhangi bir seçmenin oyunu şifrelemesine olanak tanırken güvenilir tarafın bu oyu çözebilmesini nasıl sağlarız?
Güvenilir tarafın güvenilir olduğunu ve hesaplamanın ZK kanıtını sunabildiğini nasıl garanti ederiz; peki tam olarak neyi kanıtlıyoruz?
Bunu çözmek için asimetrik şifrelemeyi benimseyebiliriz. Verileri şifrelemek ve çözmek için aynı anahtarı kullanan simetrik şifrelemeden farklı olarak asimetrik şifreleme, biri şifrelemek diğeri çözmek için olmak üzere iki farklı anahtar kullanır. ElGamal, RSA, DSA ve eliptik eğri teknikleri dahil olmak üzere birden fazla asimetrik şifreleme algoritması mevcuttur. Bu eğitimde, eliptik eğri tekniklerini, özellikle de Diffie-Hellman anahtar değişimini(ECDH)](https://www.upguard.com/blog/diffie-hellman)(ECDH)) kullanacağız.
ECDH'de hem güvenilir taraf hem de her seçmen kendi anahtar çiftlerine (bir açık anahtar ve bir özel anahtar) sahiptir. Sıfır bilgi kanıtlarına uygunluğu nedeniyle burada kullanılan Baby Jubjub eğrisi gibi eliptik eğri seçimi, kriptografik işlemlerin güvenliğini ve verimliliğini etkiler. Baby Jubjub eğrisi y^2 = x^3 + 168698 x 2 + x denklemiyle tanımlanır ve anahtar çiftleri bu eğri üzerindeki belirli nokta çiftleri olarak oluşturulur:
generateKeyPair fonksiyonunda önce güvenli bir rastgele özel anahtar oluşturuyorum, ardından eğri üzerinde önceden tanımlanmış bir nokta (genellikle taban nokta veya üreteç nokta olarak adlandırılır) üzerinde belirli bir matematiksel işlem (skaler çarpım) gerçekleştirerek karşılık gelen açık anahtarı hesaplıyorum. Kodda bu nokta Base8 olarak adlandırılmıştır. Bu çarpımın sonucu, X ve Y koordinatlarıyla gösterilen eğri üzerindeki başka bir noktadır. Ardından nokta, packPoint fonksiyonuyla kullanım kolaylığı sağlamak amacıyla bigint formatına dönüştürülür.
Seçmen, kendi özel anahtarını güvenilir tarafın açık anahtarıyla birleştirerek bir şifre oluşturur. Bu şifre, oyu şifrelemek için kullanılır. Akıllı sözleşme daha sonra şifrelenmiş oyu ve seçmenin açık anahtarını birlikte kaydeder.
Güvenilir taraf, verilerin şifresini çözmek için kendi özel anahtarını ve her seçmenin açık anahtarını kullanarak bir şifre oluşturabilir.
generateKeyPair fonksiyonunda, açık anahtarı packPoint fonksiyonuyla kolay kullanım için biçimlendirdik. Yukarıdaki kodda, unpackPoint ile onu orijinal formuna geri dönüştürüyoruz; çünkü özel anahtarı ve seçmenin açık anahtarını birleştirerek paylaşılan bir gizli anahtar oluşturmamız gerekiyor. Bu paylaşılan gizli anahtar, oyun şifresini çözmek için kullanılır.
Her oyun şifresi çözüldükten sonra sonuçları hesaplamak oldukça kolaydır! Oylar dizisinde döngü oluşturarak belirli bir seçenek için oyları biriktirmeniz yeterlidir.
ZK kanıtlarına aşina değilseniz, bunların oldukça karmaşık ancak bir o kadar da büyüleyici bir teknoloji olduğunu belirtelim. ZK kanıtları, bir tarafın değerin kendisi hakkında herhangi bir bilgi açıklamadan başka bir tarafa belirli bir değeri bildiğini kanıtlayabildiği bir yöntemdir. Özünde, ayrıntıları paylaşmadan bir şeyin doğruluğunu onaylamanın bir yoludur. Üstelik herkes bu kanıtın doğru olup olmadığını doğrulayabilir.
Uygulamamız için ideal olarak güvenilir taraf, şifrelenmiş oyları alıp şifrelerini çözebildiğini ve her seçeneğin aldığı oy sayısını hesaplayabildiğini kanıtlamalıdır. Bu durumda "gizli" anahtar, güvenilir tarafın özel anahtarıdır. Basitlik adına, yalnızca akıllı sözleşmede taahhüt edilen açık anahtarla eşleşen bir özel anahtarın sahipliğini kanıtlıyoruz. Daha önce belirtildiği gibi, oylar şifreyi oluşturmak için bu anahtarı kullanarak oyu şifreler.
Bu amaçla, Ethereum üzerinde zkSNARK'lar için bir araç kutusu olan ZoKrates'ı kullanacağız. ZoKrates, programınızı üst düzey bir dilde belirtmekten hesaplama kanıtları oluşturmaya ve bu kanıtları Solidity'de doğrulamaya kadar dapp'inizde doğrulanabilir hesaplamayı kullanmanıza yardımcı olur.
Kullandığım basit ZK programı şudur:
Argüman listesinde görebileceğiniz gibi, pk bir genel argüman, sk ise özel bir argümandır. context de geneldir. Yalnızca kanıtlayıcı (güvenilir taraf) sk'yı bilir; ancak pk, akıllı sözleşmede yer aldığı için herkes tarafından bilinir. context, anahtar çifti oluşturmak için seçtiğimiz eğriyle ilgili parametrelerdir.
Yukarıdaki kod parçacığında, bir kanıt oluşturmak için ZoKrates JS SDK'sını kullanıyorum. Akış, ZoKrates belgelerinde belgelenenle benzerdir. Amacımız ZoKrates programını kullanarak bir kanıt oluşturmaktır; bu nedenle computeWitness fonksiyonuna üç argüman iletiyoruz: pk (genel argüman), sk (özel argüman) ve context. Bunlar bir tanık oluşturmak için kullanılır ve bu tanık daha sonra kanıt oluşturmak için kullanılır.
Argümanın şu bölümünü merak ediyor olabilirsiniz:
context, uygulama genelinde kullandığımız belirli Baby JubJub eğrisiyle ilgili verileri sağlar; zira birçok eğri varyasyonu kullanılabilir. Doğrulama anahtarı, kanıtlama anahtarı ve ZoKrates programı gibi dosyalar ayrı bir dizinde tutulur. Bunları almak için aşağıdaki fonksiyonu kullanıyorum:
Aşağıdaki kod parçacığı, sözleşmenin güvenilir tarafın hesapladığı sonuçları kabul ettiği sözleşmeden alınmıştır. Sözleşme, yalnızca doğrulama başarılı olduğunda sonucu kabul eder. Dışarıdan kişiler, pk'yı (sözleşmede yer alan ve herkese açık olan) ve kanıtı doğrulayıcı fonksiyona ileterek bunu doğrulayabilir:
Bu blog yazısında, oylama süreci sona erene kadar seçmenlerin tercihlerini gizli tutan ZK tabanlı özel bir oylama sistemi olan Privote'u geliştirdik. Oyları şifrelemek için eliptik eğri tekniklerini kullandık ve bunların güvenli bir şekilde nasıl çözüleceğini ve sayılacağını gösterdik. Ayrıca özel bilgileri açıklamadan oylama sürecinin bütünlüğünü doğrulamak için ZoKrates kullanarak sıfır bilgi kanıtlarını uyguladık.
Bu eğitim, blockchain üzerinde güvenli ve özel oylama sistemleri oluşturmaya ilişkin temel bir anlayış sunmaktadır. İkinci bölümde, frontend'i oluşturacak ve kullanıcıların MetaMask SDK kullanarak nasıl bağlanıp oy kullanabileceğini göstereceğiz.
Yapay zeka tarafından çevrildi. Hatalar içerebilir. Lütfen her zaman bilgileri doğrulayın.