from Crypto.Util import number
import random
# 群生成算法,输入安全参数n,返回[p, q, g],分别是模p,群的阶q,生成元g
def GroupGen(n):
p = number.getStrongPrime(2 * n)
q = (p - 1) / 2
q =(int)(q)
while True:
x = number.getRandomRange(1, p)
if number.GCD(x, p) == 1 and x != 1 and x != p-1:
break
g = x * x % p
return [p, q, g]
# 模指数运算,输入底a,指数p,模n,返回a^p % n
def ModExp(a, p, n):
if p == 0:
return 1
result = a % n
remainders = []
while p != 1:
remainders.append(p & 1)
p = p >> 1
while remainders:
rem = remainders.pop()
result = ((a ** rem) * result ** 2) % n
return result
# 群指数运算,输入模p,群的阶q,生成元g,指数i,返回g^i
def GroupExp(p, q, g, i):
return ModExp(g, i%q, p)
# GCD算法,输入整数a和b,返回d = gcd(a, b)
def GCD(a, b):
return number.GCD(a, b)
# 扩展GCD算法,输入整数a和b,返回[d, X, Y],满足d = gcd(a, b),Xa + Yb = d
def eGCD(a, b):
if b == 0:
return (a, 1, 0)
[x1, y1, x2, y2] = [1, 0, 0, 1]
while b != 0:
[q, r] = [(int)(a/b), a%b]
[a, b] = [b, r]
x = x1 - q * x2
[x1, x2] = [x2, x]
y = y1 - q * y2
[y1, y2] = [y2, y]
return [a, x1, y1]
# 求逆元算法,输入元素a,模n,返回a的逆元
def GroupInverse(a, n):
[d, X, Y] = eGCD(a, n)
if d != 1:
return 0
return X % n
# 群内乘法,输入群元素a和b,模p,返回a * b % p
def GroupTimes(a, b, p):
return a * b % p
# 随机生成一个群元素,输入模p,群的阶q,生成元g,返回群中的一个随机元素
def GroupPickupElement(p, q, g):
i = number.getRandomRange(1, q)
return GroupExp(p, q, g, i)
[p, q, g] = GroupGen(512)
print(g)
print(GroupExp(p, q, g, 5))
print(g ** 5 % p)
res = GroupExp(p, q, g, q-20)
print(res)
print(g ** 20 % p)
print(GroupTimes(res, GroupInverse(res, p), p))
print(GroupExp(p, q, g, 0))
print(GroupExp(p, q, g, q))
res = GroupExp(p, q, g, q+5)
print(GroupTimes(res, GroupInverse(g ** 5 % p, p), p))