[超详细保姆教程]Python3.8实现Paillier 算法
⽬录
准备⼯作
安装gmpy2, libnum2
pip install gmpy2
如果报错
Microsoft Visual C++ 14.0 or later not found
且安装 Microsoft Build Tools
仍未成功解决bug的情况下,请移步:
由于不⽀持py3.4+,所以建议到这⾥当前python和cpu版本对应的gmpy2轮⼦,再通过pip安装。
pip install /your/path/to/gmpy-xxx.whl
如果pip⼜报错,记得升级⼀下pip
pip install --upgrade pip
如果升级pip的过程中⼜⼜⼜报错, 可以去官⽹下最新版的pip⼿动安装
⾄此,准备⼯作结束
Paillier 算法原理
已经讲的⽐较详尽了,本篇不再赘述,⽽在具体实现过程中(b2ale⼤佬⽤py2.+⽽本鱼⽤py3.8)为了简化运算,本鱼做了⼀些调整:公/私钥⽣成过程中有⼏个参数:
, where and p,q are large primes.
, lcm(*):=least common multiplier
是的⼀个随机整数
, n =p ×q gcd(pq ,(p −1)(q −1))=1λ=lcm (p −1,q −1)g [1,n ]2μ=L (g mod n )mod n (λ2)−1L (x )=n
x −1
⽽当保证等长时,上述参数可以被简化:
, 注意,不是Def:means 所以不要傻傻取倒数哦:)
代码部分
虽然源代码的结果暂时没bug,但感谢评论⾥⽹友的指正,这版修改了r 的范围
import gmpy2 as gy
import random
import time
import libnum
class Paillier (object ):
def __init__(self , pubKey =None , priKey =None ):
self .pubKey = pubKey
self .priKey = priKey
def __gen_prime__(self , rs ):
p = gy .mpz_urandomb (rs , 1024)
while not gy .is_prime (p ):
p += 1
return p
def __L__(self , x , n ):
res = gy .div ((x - 1), n )
# this step is essential, directly using "/" causes bugs
# due to the floating representation in python
return res
def __key_gen__(self ):
# generate random state
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)
# originally, lmd(lambda) is the least common multiple.
# However, if using p,q of equivalent length, then lmd = (p-1)*(q-1)
if gy .gcd (n , lmd ) == 1:
# This property is assured if both primes are of equal length
break
g = n + 1
mu = gy .invert (lmd , n )
#Originally,
# g would be a random number smaller than n^2,
# and mu = (L(g^lambda mod n^2))^(-1) mod n
# Since q, p are of equivalent length, step can be simplified.
p ,q n =p ×q
λ=(p −1)(q −1)
g =n +1
μ≡ϕ(n )mod n −1ϕ(n )=(p −1)(q −1)
ϕ(n )−1ϕ(n )
1
y ≡x mod n
−1∃ y s .t .
xy mod n =1
# Since q, p are of equivalent length, step can be simplified.
self.pubKey =[n, g]
self.priKey =[lmd, mu]
return
def decipher(self, ciphertext):
n, g = self.pubKey
lmd, mu = self.priKey
m = self.__L__(gy.powmod(ciphertext, lmd, n **2), n)* mu % n
print("raw message:", m)
plaintext = libnum.n2s(int(m))
return plaintext
def encipher(self, plaintext):
m = libnum.s2n(plaintext)
n, g = self.pubKey
r = gy.mpz_random(gy.random_state(int(time.time())), n)
d(n, r)!=1:
r +=1
ciphertext = gy.powmod(g, m, n **2)* gy.powmod(r, n, n **2)%(n **2)
return ciphertext
快速排序python实现if __name__ =="__main__":
pai = Paillier()
pai.__key_gen__()
pubKey = pai.pubKey
print("Public/Private key generated.")
plaintext =input("Enter your text: ")
# plaintext = 'Cat is the cutest.'
print("Original text:", plaintext)
ciphertext = ipher(plaintext)
print("Ciphertext:", ciphertext)
deciphertext = pai.decipher(ciphertext)
print("Deciphertext: ", deciphertext)
贴⼀下结果:
Public/Private key generated.
Enter your text: cats are the cutest animals.
Original text: cats are the cutest animals.
Ciphertext: 25346052223872432090673668028369814604750247872904970940453944637708132647693204447778058880188038796678960862480 88166226931637803849333986272220945041125315917931557975212052062493951706336504223393155989634205753738938395224151579134 78818521483638617531561795493928027652014497196830699526532955698555484101254875312384844523259422728123763124984511063319
01808817957276225047415960843273067205538684823776768908998399236488360103379351910791237039327283684001428489122374617383 51150204648248232240245339217377573023666343491309516363604496626600040767617774190612878935785090364321880266896051004697 12624409449838382697849977388336435805221704875439614783529952784671928221097709456941082049380826663742523658832804808140 43509923339387330401838438181236029473156208445767317218958368213866511398303936396097673820649243814674271673628904029408 91681878211225195911700375248261273384062805381656774424409368316751196106726414797650648301645898919654099910774566212394 96364704851108910910511214178124483370083131067585774189687482961232185485196468934379056505259552779052735905755968363848 79925456617663449399435190489493249446852270503540985471716706354406219962362581099291271017280794875678261298782319015278 610120121085038719101
raw message: 10466007488176005613356960919452814639381574466217680235130285486894
Deciphertext: b'cats are the cutest animals.'
注意,当传递信息越长,⽣成的素数需要更⼤
def__gen_prime__(self, rs):
p = gy.mpz_urandomb(rs,1024)
...
以上
ref
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论