这些代码都是低效的,在很多方面,首先你不需要迭代 n 的所有互质提醒,你只需要检查欧拉函数与 n 的除数的幂。在 n 是素数的情况下,欧拉函数是 n-1。如果 n i 素数,则需要分解 n-1 并仅检查那些除法器,而不是全部。这背后有一个简单的数学原理。
第二。您需要更好的函数来为数字提供动力,假设功率太大,我认为在 python 中,您有函数 pow(g, powers, modulo) 在每个步骤中进行除法并仅获得余数(_ % modulo)。
如果您要实现 Diff & Helman 算法,最好使用安全素数。它们是这样的素数,即 p 是素数,而 2p+1 也是素数,因此 2p+1 称为安全素数。如果你得到 n = 2*p+1,那么那个 n-1(n 是素数,欧拉函数从 n 是 n-1)的除数是 1、2、p 和 2p,你只需要检查数字是否g 的 2 次方和 g 的 p 次方,如果其中一个给出 1,那么那个 g 不是原根,你可以扔掉那个 g 并选择另一个 g,下一个 g+1,如果 g^2 和 g^ p 不等于 1,以 n 为模,则 g 是一个原始根,该检查保证,除 2p 之外的所有幂将给出不同于 1 的以 n 为模的数字。
示例代码使用 Sophie Germain 素数 p 和相应的安全素数 2p+1,并计算该安全素数 2p+1 的本原根。
您可以轻松地为任何素数或任何其他数字重新编写代码,方法是添加一个函数来计算欧拉函数并找到该值的所有除数。但这只是一个演示而不是完整的代码。而且可能有更好的方法。
class SGPrime :
'''
This object expects a Sophie Germain prime p, it does not check that it accept that as input.
Euler function from any prime is n-1, and the order (see method get_order) of any co-prime
remainder of n could be only a divider of Euler function value.
'''
def __init__(self, pSophieGermain ):
self.n = 2*pSophieGermain+1
#TODO! check if pSophieGermain is prime
#TODO! check if n is also prime.
#They both have to be primes, elsewhere the code does not work!
# Euler's function is n-1, #TODO for any n, calculate Euler's function from n
self.elrfunc = self.n-1
# All divisors of Euler's function value, #TODO for any n, get all divisors of the Euler's function value.
self.elrfunc_divisors = [1, 2, pSophieGermain, self.elrfunc]
def get_order(self, r):
'''
Calculate the order of a number, the minimal power at which r would be congruent with 1 by modulo p.
'''
r = r % self.n
for d in self.elrfunc_divisors:
if ( pow( r, d, self.n) == 1 ):
return d
return 0 # no such order, not possible if n is prime, - see small Fermat's theorem
def is_primitive_root(self, r):
'''
Check if r is a primitive root by modulo p. Such always exists if p is prime.
'''
return ( self.get_order(r) == self.elrfunc )
def find_all_primitive_roots(self, max_num_of_roots = None):
'''
Find all primitive roots, only for demo if n is large the list is large for DH or any other such algorithm
better to stop at first primitive roots.
'''
primitive_roots = []
for g in range(1, self.n):
if ( self.is_primitive_root(g) ):
primitive_roots.append(g)
if (( max_num_of_roots != None ) and (len(primitive_roots) >= max_num_of_roots)):
break
return primitive_roots
#demo, Sophie Germain's prime
p = 20963
sggen = SGPrime(p)
print (f"Safe prime : {sggen.n}, and primitive roots of {sggen.n} are : " )
print(sggen.find_all_primitive_roots())
问候