为离散对数实现Pollard的Rho算法

时间:2016-05-25 13:51:45

标签: python algorithm cryptography

我正在尝试使用Pollard的rho算法来计算离散对数,该算法基于Richard Crandall和Carl Pomerance在第5.2.2节(第232页)中的书Prime Numbers: A Computational Perspective中的描述。这是我的Python代码:

def dlog(g,t,p):
    # l such that g**l == t (mod p), with p prime
    # algorithm due to Crandall/Pomerance "Prime Numbers" sec 5.2.2
    from fractions import gcd
    def inverse(x, p): return pow(x, p-2, p)
    def f(xab):
        x, a, b = xab[0], xab[1], xab[2]
        if x < p/3:
            return [(t*x)%p, (a+1)%(p-1), b]
        if 2*p/3 < x:
            return [(g*x)%p, a, (b+1)%(p-1)]
        return [(x*x)%p, (2*a)%(p-1), (2*b)%(p-1)]
    i, j, k = 1, [1,0,0], f([1,0,0])
    while j[0] <> k[0]:
        print i, j, k
        i, j, k = i+1, f(j), f(f(k))
    print i, j, k
    d = gcd(j[1] - k[1], p - 1)
    if d == 1: return ((k[2]-j[2]) * inverse(j[1]-k[1],p-1)) % (p-1)
    m, l = 0, ((k[2]-j[2]) * inverse(j[1]-k[1],(p-1)/d)) % ((p-1)/d)
    while m <= d:
        print m, l
        if pow(g,l,p) == t: return l
        m, l = m+1, (l+((p-1)/d))%(p-1)
    return False

代码包含调试输出以显示正在发生的事情。您可以在 http://ideone.com/8lzzOf运行代码,在那里您还会看到两个测试用例。第一个测试用例,遵循 d &gt; 1路径,计算正确的值。第二个测试用例在 d == 1路径之后失败。

请帮我找错。

1 个答案:

答案 0 :(得分:4)

问题1

有一件看起来很可疑的事情就是这个功能:

def inverse(x, p): return pow(x, p-2, p)

这是使用Euler's theorem计算x modulo p的模逆。如果p是素数,这很好,但是否则你需要将x提升到幂phi(p)-1。

在你的情况下,你用p-1的模数调用这个函数,这将是偶数,因此给出一个不正确的逆。

由于phi(p-1)难以计算,因此最好使用extended Euclidean algorithm for computing the inverse instead

问题2

为案例g = 83,t = 566,p = 997运行代码会产生977,而您期望为147。

事实上,977确实是83的对数,我们可以看到,如果我们计算:

>>> pow(83,977,997)
566

但它不是你期待的那个(147)。

这是因为Pollard rho方法要求g是该组的生成器。不幸的是,83不是1,2组的发电机,997因为pow(83,166,997)== 1。 (换句话说,在生成组的166个元素后,您开始重复元素。)