Exemplo n.º 1
0
def quasi_primitive(p, disc_is_minus3):
    """
    Return g s.t.
    0) 1 < g < p
    1) quadratic nonresidue modulo p
    and
    2) cubic nonresidue modulo p if p == 1 mod 3
    with p >= 3, a prime.

    For p, not a prime, condition 1 means the Jacobi symbol
    (g/p) != -1, and condition 2 means g doesn't have order
    dividing (p - 1)//3.

    if disc_is_minus3 is True, cubic nonresidue check becomes
    stricter so that g**((p-1)//3) must match with one of the
    primitive third roots of unity.
    """
    third_order = (p - 1) // 3
    for g in bigrange.range(2, p):
        # if g is not quadratic nonresidue, then skipped.
        legendre_jacobi = arith1.legendre(g, p)
        if legendre_jacobi != -1:
            continue
        # if p != 1 mod 3 or g is cubic nonresidue, it's what we need.
        if p % 3 != 1:
            return g
        cubic_symbol = pow(g, third_order, p)
        if cubic_symbol != 1:
            # g is cubic nonresidue.
            if disc_is_minus3 and pow(cubic_symbol, 3, p) != 1:
                # stricter check
                continue
            return g
    else:
        raise ValueError("p is not prime.")
Exemplo n.º 2
0
def fqiso(f_q, gfq):
    """
    Return isomorphism function of extended finite fields from f_q to gfq.
    """
    if f_q is gfq:
        return lambda x: x
    if card(f_q) != card(gfq):
        raise TypeError("both fields must have the same cardinality.")

    # find a root of f_q's defining polynomial in gfq.
    p = f_q.getCharacteristic()
    q = card(f_q)
    for i in bigrange.range(p, q):
        root = gfq.createElement(i)
        if not f_q.modulus(root):
            break

    # finally, define a function
    def f_q_to_gfq_iso(f_q_elem):
        """
        Return the image of the isomorphism of the given element.
        """
        if not f_q_elem:
            return gfq.zero
        if f_q_elem.rep.degree() == 0:
            # F_p elements
            return gfq.createElement(f_q_elem.rep)
        return f_q_elem.rep(root)

    return f_q_to_gfq_iso
Exemplo n.º 3
0
def quasi_primitive(p, disc_is_minus3):
    """
    Return g s.t.
    0) 1 < g < p
    1) quadratic nonresidue modulo p
    and
    2) cubic nonresidue modulo p if p == 1 mod 3
    with p >= 3, a prime.

    For p, not a prime, condition 1 means the Jacobi symbol
    (g/p) != -1, and condition 2 means g doesn't have order
    dividing (p - 1)//3.

    if disc_is_minus3 is True, cubic nonresidue check becomes
    stricter so that g**((p-1)//3) must match with one of the
    primitive third roots of unity.
    """
    third_order = (p - 1) // 3
    for g in bigrange.range(2, p):
        # if g is not quadratic nonresidue, then skipped.
        legendre_jacobi = arith1.legendre(g, p)
        if legendre_jacobi != -1:
            continue
        # if p != 1 mod 3 or g is cubic nonresidue, it's what we need.
        if p % 3 != 1:
            return g
        cubic_symbol = pow(g, third_order, p)
        if cubic_symbol != 1:
            # g is cubic nonresidue.
            if disc_is_minus3 and pow(cubic_symbol, 3, p) != 1:
                # stricter check
                continue
            return g
    else:
        raise ValueError("p is not prime.")
Exemplo n.º 4
0
def gen_QNR(p, d):
    '''
    generating quardratic residue
    p -- prime
    '''
    # generate random number g
    g = random.randrange(2, p)
    # 1. g has to be quadratic nonresidue
    # 2. repeat if p = 1 (mod 3) and g^((p-1)/3) = 1 (mod p)
    '''
    while jacobi(g, p) != -1 \
            or (p % 3 == 1 and pow(g, (p-1)/3, p) == 1):
        g = random.randrange(2, p)
    return g
    '''

    #while True:
     #   g = random.randrange(2, p)
    for g in bigrange.range(2, p):
        if jacobi(g, p) != -1:
            continue
        if p%3 != 1:
            return g
        cube = pow(g, (p-1)/3, p)
        if cube != 1:
            if d==-3 and pow(cube, 3, p) != 1:
                continue
            return g
Exemplo n.º 5
0
def fqiso(f_q, gfq):
    """
    Return isomorphism function of extended finite fields from f_q to gfq.
    """
    if f_q is gfq:
        return lambda x: x
    if card(f_q) != card(gfq):
        raise TypeError("both fields must have the same cardinality.")

    # find a root of f_q's defining polynomial in gfq.
    p = f_q.getCharacteristic()
    q = card(f_q)
    for i in bigrange.range(p, q):
        root = gfq.createElement(i)
        if not f_q.modulus(root):
            break

    # finally, define a function
    def f_q_to_gfq_iso(f_q_elem):
        """
        Return the image of the isomorphism of the given element.
        """
        if not f_q_elem:
            return gfq.zero
        if f_q_elem.rep.degree() == 0:
            # F_p elements
            return gfq.createElement(f_q_elem.rep)
        return f_q_elem.rep(root)

    return f_q_to_gfq_iso
Exemplo n.º 6
0
def full_euler(n, divisors):
    """
    Return True iff n is prime.

    The method proves the primality of n by the equality
    phi(n) = n - 1, where phi denotes the Euler totient.
    It requires a sequence of all prime divisors of n - 1.

    Brillhart,J. & Selfridge,J.L., Some Factorizations of $2^n\pm 1$
    and Related Results, Math.Comp., Vol.21, 87-96, 1967
    """
    m_order = n - 1
    primes = set(divisors)
    for g in bigrange.range(2, n):
        if pow(g, m_order, n) != 1:
            return False
        if 2 in primes:
            jacobi = arith1.legendre(g, n)
            if jacobi == 0:
                return False
            elif jacobi == -1:
                primes.remove(2)
        satisfied = [
            p for p in primes if p > 2 and pow(g, m_order // p, n) != 1
        ]
        if satisfied:
            primes.difference_update(satisfied)
        if not primes:
            return True
    return True  # only when n=2, flow reaches this line
Exemplo n.º 7
0
 def _parse_seq(self, options):
     """
     Parse 'options' to define trial sequaence.
     """
     if 'start' in options and 'stop' in options:
         if 'step' in options:
             trials = bigrange.range(options['start'], options['stop'], options['step'])
         else:
             trials = bigrange.range(options['start'], options['stop'])
     elif 'iterator' in options:
         trials = options['iterator']
     elif 'eratosthenes' in options:
         trials = prime.generator_eratosthenes(options['eratosthenes'])
     elif options['n'] < 1000000:
         trials = prime.generator_eratosthenes(arith1.floorsqrt(options['n']))
     else:
         trials = prime.generator()
     return trials
Exemplo n.º 8
0
 def _parse_seq(self, options):
     """
     Parse 'options' to define trial sequaence.
     """
     if 'start' in options and 'stop' in options:
         if 'step' in options:
             trials = bigrange.range(options['start'], options['stop'],
                                     options['step'])
         else:
             trials = bigrange.range(options['start'], options['stop'])
     elif 'iterator' in options:
         trials = options['iterator']
     elif 'eratosthenes' in options:
         trials = prime.generator_eratosthenes(options['eratosthenes'])
     elif options['n'] < 1000000:
         trials = prime.generator_eratosthenes(
             arith1.floorsqrt(options['n']))
     else:
         trials = prime.generator()
     return trials
Exemplo n.º 9
0
def primitive_root(p):
    """
    Return a primitive root of p.
    """
    pd = FactoredInteger(p - 1).proper_divisors()
    for i in bigrange.range(2, p):
        for d in pd:
            if pow(i, (p - 1) // d, p) == 1:
                break
        else:
            return i
Exemplo n.º 10
0
def primitive_root(p):
    """
    Return a primitive root of p.
    """
    pd = FactoredInteger(p - 1).proper_divisors()
    for i in bigrange.range(2, p):
        for d in pd:
            if pow(i, (p - 1)//d, p) == 1:
                break
        else:
            return i
Exemplo n.º 11
0
def apr(n):
    """
    apr is the main function for Adleman-Pomerance-Rumery primality test.
    Assuming n has no prime factors less than 32.
    Assuming n is spsp for several bases.
    """
    L = Status()

    rb = arith1.floorsqrt(n) + 1
    el = TestPrime()
    while el.et <= rb:
        el = el.next()

    plist = el.t.factors.keys()
    plist.remove(2)
    L.yet(2)
    for p in plist:
        if pow(n, p-1, p*p) != 1:
            L.done(p)
        else:
            L.yet(p)
    qlist = el.et.factors.keys()
    qlist.remove(2)
    J = JacobiSum()
    for q in qlist:
        for p in plist:
            if (q-1) % p != 0:
                continue
            if not L.subodd(p, q, n, J):
                return False
        k = arith1.vp(q-1, 2)[0]
        if k == 1:
            if not L.sub2(q, n):
                return False
        elif k == 2:
            if not L.sub4(q, n, J):
                return False
        else:
            if not L.sub8(q, k, n, J):
                return False
    for p in L.yet_keys():
        if not L.subrest(p, n, el.et, J):
            return False
    r = int(n)
    for _ in bigrange.range(1, el.t.integer):
        r = (r*n) % el.et.integer
        if n % r == 0 and r != 1 and r != n:
            _log.info("%s divides %s.\n" %(r, n))
            return False
    return True
Exemplo n.º 12
0
def apr(n):
    """
    apr is the main function for Adleman-Pomerance-Rumery primality test.
    Assuming n has no prime factors less than 32.
    Assuming n is spsp for several bases.
    """
    L = Status()

    rb = arith1.floorsqrt(n) + 1
    el = TestPrime()
    while el.et <= rb:
        el = next(el)

    plist = list(el.t.factors.keys())
    plist.remove(2)
    L.yet(2)
    for p in plist:
        if pow(n, p - 1, p * p) != 1:
            L.done(p)
        else:
            L.yet(p)
    qlist = list(el.et.factors.keys())
    qlist.remove(2)
    J = JacobiSum()
    for q in qlist:
        for p in plist:
            if (q - 1) % p != 0:
                continue
            if not L.subodd(p, q, n, J):
                return False
        k = arith1.vp(q - 1, 2)[0]
        if k == 1:
            if not L.sub2(q, n):
                return False
        elif k == 2:
            if not L.sub4(q, n, J):
                return False
        else:
            if not L.sub8(q, k, n, J):
                return False
    for p in L.yet_keys():
        if not L.subrest(p, n, el.et, J):
            return False
    r = int(n)
    for _ in bigrange.range(1, el.t.integer):
        r = (r * n) % el.et.integer
        if n % r == 0 and r != 1 and r != n:
            _log.info("%s divides %s.\n" % (r, n))
            return False
    return True
Exemplo n.º 13
0
 def primitive_element(self):
     """
     Return a primitive element of the field, i.e., a generator of
     the multiplicative group.
     """
     fullorder = card(self) - 1
     if self._orderfactor is None:
         self._orderfactor = factor_misc.FactoredInteger(fullorder)
     for i in bigrange.range(self.char, card(self)):
         g = self.createElement(i)
         for p in self._orderfactor.prime_divisors():
             if g ** (fullorder // p) == self.one:
                 break
         else:
             return g
Exemplo n.º 14
0
 def primitive_element(self):
     """
     Return a primitive element of the field, i.e., a generator of
     the multiplicative group.
     """
     fullorder = card(self) - 1
     if self._orderfactor is None:
         self._orderfactor = factor_misc.FactoredInteger(fullorder)
     for i in bigrange.range(self.char, card(self)):
         g = self.createElement(i)
         for p in self._orderfactor.prime_divisors():
             if g**(fullorder // p) == self.one:
                 break
         else:
             return g
Exemplo n.º 15
0
def next_disc(d, absbound):
    """
    Return fundamental discriminant D, such that D < d.
    If there is no D with |d| < |D| < absbound, return False
    """
    # -disc % 16
    negdisc_mod16 = (3, 4, 7, 8, 11, 15)
    for negdisc in bigrange.range(-d + 1, absbound):
        if negdisc % 16 not in negdisc_mod16:
            continue
        if negdisc % 2 == 1 and not squarefree.trial_division(negdisc):
            continue
        if arith1.issquare(negdisc):
            continue
        return -negdisc
    return False
Exemplo n.º 16
0
def next_disc(d, absbound):
    """
    Return fundamental discriminant D, such that D < d.
    If there is no D with |d| < |D| < absbound, return False
    """
    # -disc % 16
    negdisc_mod16 = (3, 4, 7, 8, 11, 15)
    for negdisc in bigrange.range(-d + 1, absbound):
        if negdisc & 15 not in negdisc_mod16:
            continue
        if negdisc & 1 and not squarefree.trial_division(negdisc):
            continue
        if arith1.issquare(negdisc):
            continue
        return -negdisc
    return False
Exemplo n.º 17
0
def trialDivision(n, bound=0):
    """
    Trial division primality test for an odd natural number.
    Optional second argument is a search bound of primes.
    If the bound is given and less than the sqaure root of n
    and True is returned, it only means there is no prime factor
    less than the bound.
    """

    if bound:
        m = min(bound, arith1.floorsqrt(n))
    else:
        m = arith1.floorsqrt(n)
    for p in bigrange.range(3, m + 1, 2):
        if not (n % p):
            return False
    return True
Exemplo n.º 18
0
def trialDivision(n, bound=0):
    """
    Trial division primality test for an odd natural number.
    Optional second argument is a search bound of primes.
    If the bound is given and less than the sqaure root of n
    and True is returned, it only means there is no prime factor
    less than the bound.
    """

    if bound:
        m = min(bound, arith1.floorsqrt(n))
    else:
        m = arith1.floorsqrt(n)
    for p in bigrange.range(3, m+1, 2):
        if not (n % p):
            return False
    return True
Exemplo n.º 19
0
def e3_Fp(x, p):
    """
    p is prime
    0 = x[0] + x[1]*t + x[2]*t**2 + x[3]*t**3
    """
    x.reverse()
    lc_inv = finitefield.FinitePrimeFieldElement(x[0], p).inverse()
    coeff = []
    for c in x[1:]:
        coeff.append((c * lc_inv).n)
    sol = []
    for i in bigrange.range(p):
        if (i**3 + coeff[0]*i**2 + coeff[1]*i + coeff[2]) % p == 0:
            sol.append(i)
            break
    if len(sol) == 0:
        return sol
    X = e2_Fp([coeff[1] + (coeff[0] + sol[0])*sol[0], coeff[0] + sol[0], 1], p)
    if len(X) != 0:
        sol.extend(X)
    return sol
Exemplo n.º 20
0
def e3_Fp(x, p):
    """
    p is prime
    0 = x[0] + x[1]*t + x[2]*t**2 + x[3]*t**3
    """
    x.reverse()
    lc_inv = finitefield.FinitePrimeFieldElement(x[0], p).inverse()
    coeff = []
    for c in x[1:]:
        coeff.append((c * lc_inv).n)
    sol = []
    for i in bigrange.range(p):
        if (i**3 + coeff[0] * i**2 + coeff[1] * i + coeff[2]) % p == 0:
            sol.append(i)
            break
    if len(sol) == 0:
        return sol
    X = e2_Fp([coeff[1] + (coeff[0] + sol[0]) * sol[0], coeff[0] + sol[0], 1],
              p)
    if len(X) != 0:
        sol.extend(X)
    return sol
Exemplo n.º 21
0
def by_primitive_root(n, divisors):
    """
    Return True iff n is prime.

    The method proves the primality of n by existence of a primitive
    root.  It requires a sequence of all prime divisors of n - 1.

    Lehmer,D.H., Tests for primality by the converse of Fermat's
    theorem, Bull.Amer.Math.Soc, Vol.33, pp.327-340, 1927.
    """
    m_order = n - 1
    primes = tuple(p for p in divisors if p > 2)
    for g in bigrange.range(2, n):
        jacobi = arith1.legendre(g, n)
        if jacobi == 0:
            return False
        elif jacobi == 1:
            continue
        if pow(g, m_order, n) != 1:
            return False
        if all(pow(g, m_order // p, n) != 1 for p in primes):
            return True
    return True  # only when n=2, flow reaches this line
Exemplo n.º 22
0
def embedding(f_q1, f_q2):
    """
    Return embedding homomorphism function from f_q1 to f_q2,
    where q1 = p ** k1, q2 = p ** k2 and k1 divides k2.
    """
    if card(f_q1) == card(f_q2):
        return fqiso(f_q1, f_q2)
    # search multiplicative generators of both fields and relate them.
    # 0. initialize basic variables
    p = f_q2.getCharacteristic()
    q1, q2 = card(f_q1), card(f_q2)
    q1_mult_order, q2_mult_order = q1 - 1, q2 - 1

    # 1. find a multiplicative generator of f_q2
    for i in bigrange.range(p, q2):
        f_q2_gen = f_q2.createElement(i)
        if f_q2.order(f_q2_gen) == q2_mult_order:
            break
    f_q2_subgen = f_q2_gen**((q2 - 1) // (q1 - 1))

    # 2.1 minimal polynomial of g = f_q2_gen ** ((q2 - 1) // (q1 - 1))
    #   minpoly = (X - g)(X - g**p)...(X - g**(p**(k1 - 1)))
    q, gpow = 1, f_q2_subgen
    linear_factors = []
    while q < q2:
        linear_factors.append(univar.BasicPolynomial({0: gpow, 1: f_q2.one}))
        # finally, raise power (Frobenius map).
        q *= p
        gpow **= p
    minpoly = arith1.product(linear_factors)
    # 2.2 minpoly has f_q2 coefficints but they are indeed f_p elements
    minpoly = univar.BasicPolynomial([(d, c.rep[0]) for (d, c) in minpoly])

    # 3. find a multiplicative generator of f_q1
    for i in bigrange.range(p, q1):
        f_q1_gen = f_q1.createElement(i)
        if f_q1.order(f_q1_gen) == q1_mult_order:
            break

    # 4. find f_q1_gen ** c of a root of minpoly and let it f_q1_gen
    for c in bigrange.range(1, q1):
        if gcd.coprime(c, q1_mult_order):
            if not minpoly(f_q1_gen**c):
                break
    f_q1_gen = f_q1_gen**c

    # 5. solve DLP:
    #   x_1 = f_q1_gen ** t
    #   (Here uses "brute force" method)
    x_1 = f_q1.createElement(p)
    gpow = f_q1_gen
    for i in bigrange.range(1, q):
        if gpow == x_1:
            image_of_x_1 = f_q2_subgen**i
            break
        gpow *= f_q1_gen

    # finally, define a function
    def f_q1_to_f_q2_homo(f_q1_elem):
        """
        Return the image of the isomorphism of the given element.
        """
        if not f_q1_elem:
            return f_q2.zero
        if f_q1_elem.rep.degree() == 0:
            # F_p elements
            return f_q2.createElement(f_q1_elem.rep)
        return f_q1_elem.rep(image_of_x_1)

    return f_q1_to_f_q2_homo