有关Paillier算法的匿名投票机制

本文介绍了如何使用Python实现Paillier算法,包括库的安装、基本操作(初始化、加密、解密和加法同态性)以及在电子投票场景中的应用。然而,文中也提到了公钥使用的问题,需要进一步改进以增强安全性。
摘要由CSDN通过智能技术生成

其实就是一次课堂作业,写一下过程

Paillier算法的原理很简单,如图所示

首先是建立一个新环境

我使用anaconda建立Python的新环境,直接运行prompt输入 conda create –n python27_env (环境名) python=2.7 以创建 python 2.7 环境

conda create -n Paillier python=2.7

用到的库有gmpy2,time,binascii,其中只有gmpy2需要下载,在虚拟环境下直接

conda install gmpy2

 

其余两个库可直接引入

其次是写Paillier库

这个库里面包含初始化(init)、计算函数(L)、密钥生成(keygen)、加密和解密函数构成的。

直接贴代码

import gmpy2 as gy
import time
import binascii
#gmpy2为对大整数运算的库函数,包含初始化、求最大公因数、求逆元、判断奇偶数素数合数取余开方等运算

class Paillier(object):

    def __init__(self, pubKey=None, privateKey=None):
        self.pubKey = pubKey
        self.privateKey = privateKey

    def __L__(self, x, n):
        res = (x - 1) // n
        return res

    def gen_prime(self, rs):
        p = gy.mpz_urandomb(rs, 1024)
        while not gy.is_prime(p):
            p += 1
        return p

    def keygen(self):
        while True:
            rs = gy.random_state(int(time.time()))
            p = self.gen_prime(rs)
            q = self.gen_prime(rs)
            n = p * q
            lmd = (p - 1) * (q - 1)
            if gy.gcd(n, lmd) == 1:
                break
        g = n + 1
        mu = gy.invert(lmd, n)
        self.pubKey = [n, g]
        self.privateKey = [lmd, mu]

    def encrypt(self, plaintext):
        m = gy.mpz(plaintext)  # Ensure plaintext is converted to mpz
        n, g = self.pubKey
        r = gy.mpz_random(gy.random_state(int(time.time())), n)
        while gy.gcd(n, r) != 1:
            r += 1
        ciphertext = (gy.powmod(g, m, n ** 2) * gy.powmod(r, n, n ** 2)) % (n ** 2)
        return ciphertext

    def decrypt(self, ciphertext):
        n, _ = self.pubKey
        lmd, mu = self.privateKey
        m = self.__L__(gy.powmod(ciphertext, lmd, n ** 2), n)
        plaintext = m*mu %n
        return plaintext

    def add(self, ciphertext1, ciphertext2):
        n, _ = self.pubKey
        result = (ciphertext1 * ciphertext2) % (n ** 2)
        return result

这样一个简单的Paillier库就完成了,我们进行一个测试

新建test.py:

import Paillier

pai = Paillier.Paillier()
pai.keygen()
pubKey = pai.pubKey
print("密钥已生成")
plaintext1 = input("请输入第一个明文: ")
plaintext2 = input("请输入第二个明文: ")
print("公钥:",pubKey)
ciphertext1 = pai.encrypt(plaintext1)
ciphertext2 = pai.encrypt(plaintext2)
print("第一个明文加密结果", ciphertext1)
print("第二个明文加密结果", ciphertext2)
detext1=pai.decrypt(ciphertext1)
detext2=pai.decrypt(ciphertext2)
print("第一个密文解密结果:",detext1)
print("第二个密文解密结果:",detext2)
re=pai.add(ciphertext1, ciphertext2)
print("两密文相乘结果为:",re)
deciphertext = pai.decrypt(re)
print("密文相乘解密得到明文: ", deciphertext)

Paillier算法具有加法同态性,即密文相乘(模n²)后解密的结果为明文相加的结果,例如输入111与222,输出密文相乘解密得到的明文为333

经过测试后可以看出我们的算法是可行的,那么进行匿名投票算法的编写

新建ElectronicVoting.py

在这里,我们规定每位投票者有且仅有一票,即最多投一票,可以选择不投,但是由于票数均为零对结果无影响我们这里不予考虑,假设每位投票者的票均会投出。

代码如下:

import Paillier

print("规定每位投票者只有一票且必须投出,投票者将每位候选者的票数加密后发送给统计者,统计者进行相乘,而后公布者进行解密")
x=input("请输入候选者人数数量")
y=input("请输入投票者人数数量")
n=eval(y)
pai = Paillier.Paillier()
pai.keygen()
pubKey = pai.pubKey
s=[]
for i in range(0,n):
    print("请第",i+1,"名投票者为候选者投票")
    l=[]
    for j in range(0,eval(x)):
        print("请为第",j+1,"名投票者投票:")
        c=input()
        l.append(pai.encrypt(c))#将每位投票者对每位候选人的票数加密后存储到列表中
    s.append(l)
q=[]
for i in range(0,eval(x)):
    re=1
    for j in range(0,n):
        re = (re * s[j][i]) % (pai.pubKey[0] ** 2)#利用加法同态性进行票数相乘计算
    print("第",i+1,"位候选者获得了",pai.decrypt(re),"张选票")
    q.append(pai.decrypt((re)))
max_votes = max(q)
winner_index = q.index(max_votes) + 1  # 候选者编号从1开始
print("\n获得最多票数的候选者是第", winner_index, "位,共获得", max_votes, "张选票。")

即可得到结果,结果如图

总结

在这段代码中能够完成对于票数的匿名统计,但是还存在一些问题,比如每位投票者加密使用的公钥都是一样的,这样也许某位投票者能够根据自己结果加密出来的密文推断出他人投票的结果,后续还需改进

感谢大家收看

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值