由于在 Python 标记下询问了此问题的重复项,因此这里是婴儿步、巨步的 Python 实现,正如@MarkBeyers 指出的那样,这是一种合理的方法(只要模数不太大):
def baby_steps_giant_steps(a,b,p,N = None):
if not N: N = 1 + int(math.sqrt(p))
#initialize baby_steps table
baby_steps = {}
baby_step = 1
for r in range(N+1):
baby_steps[baby_step] = r
baby_step = baby_step * a % p
#now take the giant steps
giant_stride = pow(a,(p-2)*N,p)
giant_step = b
for q in range(N+1):
if giant_step in baby_steps:
return q*N + baby_steps[giant_step]
else:
giant_step = giant_step * giant_stride % p
return "No Match"
在上述实现中,即使p 在密码学上很大,也可以将显式N 传递给小指数。只要指数小于N**2,它就会找到指数。当N 被省略时,指数总是会被找到,但如果p 太大,则不一定在你的生命周期或你的机器内存中找到。
例如,如果
p = 70606432933607
a = 100001
b = 54696545758787
然后 'pow(a,b,p)' 计算结果为 67385023448517
和
>>> baby_steps_giant_steps(a,67385023448517,p)
54696545758787
这在我的机器上花了大约 5 秒钟。对于这些大小的指数和模数,我估计(基于时间实验)蛮力需要几个月的时间。