Ejemplo n.º 1
0
def primitive_root(n):
    """ Finds a primitive root modulo n using Gauss's algorithm
        and some related facts. """
    fact = factorize(n)
    if len(fact) == 1:
        p, e = fact[0]
        if p == 2:
            if e <= 2:
                return n // 2
            return

        pr = _primitive_root(p)
        if e > 1 and pow(pr, p - 1, p ** 2) == 1:
            pr += p
        return pr
    elif len(fact) == 2:
        if fact[0] != (2, 1):
            return

        p, e = fact[1]
        pr = _primitive_root(p)
        if e > 1 and pow(pr, p - 1, p ** 2) == 1:
            pr += p
        if pr % 2 == 0:
            pr += p ** e
        return pr
Ejemplo n.º 2
0
def algebras(m_maxs):
  """
  Generator for the possible algebras.

  Args:
      m_maxs: Maximum possible m values given p and d as a tuple e.g. (m, p, d).
  Returns:
      A 5-tuple ( m, p, d, phi_m, nSlots ) for the algebra.
  Usage:
      >>> print( '\\n'.join(map(str,algebras( ((24, 5, 2),) ))))
      (2, 5, 1, 1, 1)
      (4, 5, 1, 2, 2)
      (8, 5, 2, 4, 2)
      (3, 5, 2, 2, 1)
      (6, 5, 2, 2, 1)
      (12, 5, 2, 4, 2)
      (24, 5, 2, 8, 4)
  """
  # Generate the divisors for each max_m
  for m_max,p,d in m_maxs:
    factors = numth.factorize(m_max)
    for mFactors in numth.divisorsFactors(factors):
      d_real = d
      m = numth.calcDivisor(mFactors)
      if m == 1:
        continue

      phi_m = numth.phi(mFactors)

      # Correct for order of p in mod m a.k.a. d
      phimFactors = numth.factorize(phi_m)
      for e in sorted(numth.divisors(phimFactors)):
        if p**e % m == 1:
          d_real = e
          break

      nSlots, r = divmod(phi_m, d_real)
      if r != 0:
         raise ArithmeticError("Fractional nslots should not exist.")

      # SolnObj just a 5-tuple ( m, p, d, phi_m, nSlots )
      yield (m,p,d_real,phi_m,nSlots)
Ejemplo n.º 3
0
def _log_pohlig_hellman(g, a, p):
    """ For internal use only - see log() for other purposes.
        Finds the discreet logarithm log_g(a) modulo p using the 
        Pohlig-Hellman algorithm. """
    o = order(g, p)
    fact = factorize(o)
    rems, mods = [], []
    for q, e in fact:
        d = q ** e
        ne = o // d
        rem = _log_pohlig_hellman_pp(pow(g, ne, p), pow(a, ne, p), p, q, e)
        rems.append(rem)
        mods.append(d)

    return solve_mult_cong(zip(rems, mods))[0]
Ejemplo n.º 4
0
def pow_mod(a, e, n):
    """ Computes a^e mod n using Carmichael's function. """
    fact = factorize(n)
    rems, mods = [], []
    for p, exp in fact:
        d = p ** exp
        mods.append(d)
        if a % p == 0 and e > exp:
            rems.append(0)
        else:
            rems.append(pow(a % d, e % carmichael(d), d))
            
    if len(rems) > 1:
        R = solve_mult_cong(zip(rems, mods))[0]
    else:
        R = rems[0]

    return R
Ejemplo n.º 5
0
def solve_quadr(a, b, c, n):
    """ Finds the solutions of the congruence aX^2 + bX + c = 0 (mod n). """
    rems, mods = [], []
    for q, e in factorize(n):
        rem = _solve_quadr_pk(a, b, c, q, e)
        if not rem:
            rems = []
            break
        rems.append(rem)
        mods.append(q ** e)

    if len(rems) > 1:
        sols = [solve_mult_cong(zip(rs, mods))[0] for rs in product(*rems)]
    elif len(rems) == 1:
        sols = rems[0]
    else:
        sols = []

    return sols
Ejemplo n.º 6
0
def root(n, a, m):
    """ Finds the solutions of the equation x^n = a (mod m). """
    rems, mods = [], []
    for q, e in factorize(m):
        if q == 2 and e > 2:
            r = _root_p2(n, a, e)
        else:
            r = _root_pp(n, a, q, e)
        if r is None:
            return
        rems.append(r)
        mods.append(q ** e)

    if len(rems) > 1:
        sols = [solve_mult_cong(zip(rs, mods))[0] for rs in product(*rems)]
    else:
        sols = rems[0]

    return sols
Ejemplo n.º 7
0
def parsePrimeRange(rangeStr):
  """
  Parses the ranges and numbers given to it, but only of primes.

  Args:
      rangeStr: a string e.g. '2-5,7,10-11'
  Returns:
       A list of prime numbers to try out.
  Usage:
      >>> parsePrimeRange('2-5,7,10-11')
      [2, 3, 5, 7, 11]
  """

  p_prime = list(\
              filter(lambda x: numth.factorize(x)[x] == 1, \
              parseRange(rangeStr))\
            )
  if len(p_prime) == 0:
    raise argparse.ArgumentTypeError("No primes found in range given.")

  return p_prime
Ejemplo n.º 8
0
if __name__ == "__main__":

  parser = argparse.ArgumentParser(description="")
  parser.add_argument("-p", type=parsePrimeRange, default="2",
    help="Prime number for plaintext space.")
  parser.add_argument("-d", type=parseRange, default="1",
    help="How many coefficients in a slot (the order of p in ZmStar).")
  parser.add_argument("--self-test", action="store_true",
    help="Run doctest on itself.")
  args = parser.parse_args()

  # Run doctest instead of normal operation
  if args.self_test:
    import doctest
    print(doctest.testmod())
    exit(0)

  # Generator for m_max(s)
  m_maxs = [ (p**d - 1, p, d) for p in args.p for d in args.d ]

  # SolnObj just a 5-tuple ( m, p, d, phi_m, nSlots )
  solns = sorted( algebras(m_maxs) )

  m_max = max(m_maxs)
  minWidths = [ math.ceil(math.log10(t)) for t in m_max ]
  minWidths.append(
    math.ceil(math.log10(numth.phi(numth.factorize(m_max[0])))))
  minWidths.append(minWidths[-1])

  printTable( ('m','p','d','phi(m)','nSlots'), solns, minWidths)