1

I've implemented Pollard's Rho for logarithms using Sage, as the following program stored in pollardrho.py.

def pollardrho(g, h, G):
    k, m = 1, 0
    t = g**k * h**m
    i, j = 1, 0
    r = g**i * h**j

    def step(t, k, m):
        if lift(t) % 3 == 0:
            return (t * g, k+1, m)
        if lift(t) % 3 == 1:
            return (t * h, k, m+1)
        if lift(t) % 3 == 2:
            return (t ** 2, 2*k, 2*m)

    while True:
        t, k, m = step(t, k, m)
        r, i, j = step(*step(r, i, j))
        if t == r:
            print("Found a cycle")
            print("g^%s h^%s == g^%s h^%s" % (k, m, i, j))
            print("g^(%s - %s) == h^(%s - %s)" % (i, k, m, j))
            l = g.multiplicative_order()
            print("(%s - %s) / (%s - %s) %% %s" % (i, k, m, j, l))
            return (i - k) / (m - j) % l  # this is where everything goes wrong.

Running this with G = GF(1013), g = G(3), h = G(245) gives the following output:

sage: pollardrho(g, h, G)
Found a cycle
g^262 h^14 == g^16870 h^1006
g^(16870 - 262) == h^(14 - 1006)
(16870 - 262) / (14 - 1006) % 1012
995

However:

sage: (16870 - 262) / (14 - 1006) % 1012
375

Note that this is a completely different result!

If I check the types of i, j, k, m, they are all of type int...

Thom Wiggers
  • 6,938
  • 1
  • 39
  • 65

2 Answers2

1

It turns out that typing an integer in the sage shell gives a different result than doing the same inside a python program that uses Sage libraries:

sage: type(1234)
<type 'sage.rings.integer.Integer'>

This isn't the same as the <type 'int'> I got inside of my own program!

Using k, m = Integer(1), Integer(0) solved my problem and I now get the correct discrete log.

Thom Wiggers
  • 6,938
  • 1
  • 39
  • 65
1

To elaborate on Thom's answer, in a .py file you can't use the various preparsing things that Sage does - in particular, ints are ints. Importing from sage.rings.integer.Integer (or from sage.all) in your file could work, or (and I recommend this) just making your file .sage extension instead of .py is the easiest, and least likely to run into other subtle differences.

kcrisman
  • 4,374
  • 20
  • 41
  • Do `.sage` files still work with 'from x import y' or do I need to use `load()` in that case? – Thom Wiggers Oct 03 '15 at 08:30
  • Hmm, that's a good question. I assume the answer is `load()` since I've never done anything else (and it's easier for me), but since the `.sage` file is then preparsed into a `.py` file I suppose it's possible that works too, if you've created some module. Try it and see! – kcrisman Oct 03 '15 at 08:34
  • Since I'm now at a computer instead of on my phone I've been able to test it, it doesn't appear to work. So that's one unfortunate downside. – Thom Wiggers Oct 03 '15 at 08:53
  • For completeness, doing `load('pollardrho.py')` also doesn't replace ints by `Integer`, while `load('pollardrho.sage')` does. So it's not just the `import` statement that doesn't do magic, it really does depend on the file extension. – Thom Wiggers Oct 03 '15 at 08:58