from random import randint

import math

import gmpy2 as gy

def prime():   #随机生成一个3位的大素数 本人电脑算力有限,无法实现百位的大素数

    def miller_rabin(p):   #素性检测

        if p == 1: return False

        if p == 2: return True

        if p % 2 == 0: return False

        m, k, = p - 1, 0

        while m % 2 == 0:

            m, k = m // 2, k + 1

        a = randint(2, p - 1)

        x = pow(a, m, p)

        if x == 1 or x == p - 1: return True

        while k > 1:

            x = pow(x, 2, p)

            if x == 1: return False

            if x == p - 1: return True

            k = k - 1

        return False

    def is_prime(p, r = 40):   #判断是否为素数

        for i in range(r):

            if miller_rabin(p) == False:

                return False

        return True

    min=10 ** 2

    max=(10 **3)-1

    x=randint(min,max)

    while is_prime(x) == False:

        x=randint(min,max)

    return x

def keygen():  #生成密钥

    global p,q,n,l,g,u

    p = prime()

    q = prime()

    while (p==q):

        q = prime()

    n=p*q

    while gy.gcd(n,(p-1)*(q-1))!=1:

        p = prime()

        q = prime()

        while (p==q):

            q = prime()

        n=p*q

    l=(p-1)*(q-1)

    g=n+1

    u=gy.invert(l,n)

def encode(m):  #加密

    r=randint(1,50)

    c=(pow(g,m)*pow(r,n))%(n*n)

    return c

def decode(c):   #解密

    m=(((pow(c,l)%(n*n))-1)/n*u)%n

    return m

if __name__ == '__main__':

    keygen()   #生成密钥

    m1=eval(input("请输入第一个明文:"))

    m2=eval(input("请输入第二个明文:"))

    c1=encode(m1)

    c2=encode(m2)

    print("对第一个明文加密后得到密文:%d" % c1)

    print("对第二个明文加密后得到密文:%d" % c2)

    c=c1*c2

    print("两密文相乘得到:%d" % c)

    m=decode(c)

    print("密文相乘后解密得到的明文为:%d" % m)

 编写paillier.py文件,代码如上

  其中prime()函数用于生成素数,keygen()函数用于生成密钥,encode()函数用于加密,decode()函数用于解密

  运行结果如下图所示:

3.创建python代码文件,模拟实现基于Paillier 算法的匿名电子投票流程

 

代码如下:

import paillier
def vote():
    global hn,tn
    hn = eval(input("请设置候选者人数:"))
    tn = eval(input("请设置投票者人数:"))
    li_h=[]
    for i in range(1,hn+1):
        li_t=[]
        print("----------请第%d名投票者为候选者投票----------" % i)
        for k in range(1,tn+1):
            print("请为第%d名候选者投票:" %
                  k,end ='')
            n=eval(input())
            li_t.append(n)
        li_h.append(li_t)
    return li_h
def count(li_h):  
    paillier.keygen()
    global li_c
    li_c=[]
    for i in range(1,hn+1):
        c=1
        for k in range(1,tn+1):
            c=c*paillier.encode(li_h[k-1][i-1])
        li_c.append(c)
        print("第{}位候选人获得的选票票数的加密结果为{}".format(i,c))
def unveil():
    li_u=[]
    for i in range(1,hn+1):
        print("第{}位候选人获得了{}张选票:".format(i,int(paillier.decode(li_c[i-1]))))
        li_u.append(int(paillier.decode(li_c[i-1])))
    max = li_u[0]
    max_h=1
    for i in range(1,(hn-1)):
        if max<li_u[i]:
            max = li_u[i]
            max_h=i+1
    print("最终第{}位候选人获得的选票最多,为{}张".format(max_h,max))   
li_h=vote()
count(li_h)
unveil()


其中vote()函数用于进行投票,并以数组的形式返回投票结果,count函数用于计数,unveil函数用于公布结果

实验结果如下图所示

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐