Given a pair of primes $g < p$, is there an efficient test if $g$ is a generator of the group $\mathbb{Z}_p^*$?

70 Views Asked by At

There are posts around on how to find generators, but I want to start from a supposed guess, a prime candidate $g$ for a generator of a for the multiplicative group of units for the prime-sized field $\mathbb{Z}_p$.

So my precise question:

  • [Main Qu] suppose we have two primes $g$ and $p$ such that $g < p$: is $g$ a generator for $\mathbb{Z}_p^*$?

On the small chance people use different notation, I'll clarify that $\mathbb{Z}_p^* = \{1, 2, \dots, p-1\}$, with the group operator of "multiplication-modulo-$p$".

As a side question, which might be irritating people that think I'm asking a dumb question (I might well be!!):

  • [Side Qu] Is there any benefit in guessing a generator $g$ such that $gcd(g, p) = 1$? This is the main logic in my choice that $g$ is chosen to be prime in advance.

I have a tentative solution in python below, but it is so slow that I can't verify it, and it may be wrong. I don't know.

EDIT: I tidied the modulo power function so that it doesn't try to compute the huge value and then modulerise it. My program is still taking forever even with the small test cases...

EDIT again, again from @FredH's comments. Replace the last line of my modPow function with an auxillary m to square. But it is STILL taking longer than I care to wait just to terminate the following script. (I'm using an Intel Core i9 CPU with 16GB memory, so I don't think my laptop is the problem!)

    def modPow(g, n, p):
        if (g >= p):
            g %= p
        if n == 0:
            return 1
        if n == 1:
            return g
        if n == 2:
            return (g*g)%p
        if (n%2):
            return (g*modPow(g, n-1, p))%p
        else:
            m = modPow(g, n/2, p)
            return (m*m)%p



    def isGen(g, p=9576890767):
        factors = []  # of p-1
        M = p-1
        while M > 1:
            d = 2
            if (M%d == 0):
                factors.append(d)
                M /= d
            else:
                d += 1
                d += ( (d%2) == 0)  # skip evens
        factors = list(set(factors))  # remove duplicates
        for q in factors:
            if modPow(g, (p-1)/q, p) == 1:
                return False
        return True


    print(isGen(2, 7))
    print(isGen(2, 13))
    print(isGen(5, 101))