Esempio n. 1
0
def _log_rho(g, a, p, *, partition="d"):
    """ For internal use only - see log() for other purposes.
        Finds the discreet logarithm log_g(a) modulo p using 
        Pollard's rho algorithm. """
    phi_p = phi(p)
    for i, j in product(range(phi_p), repeat=2):
        u, v = [i], [j]
        x = [a ** u[0] * g ** v[0] % p]
        for i in count(1):
            if partition == "d":
                r = x[-1]
                if r < p // 3:
                    x.append(x[-1] ** 2 % p)
                    u.append(2 * u[-1] % phi_p)
                    v.append(2 * v[-1] % phi_p)
                elif r < 2 * p // 3:
                    x.append(a * x[-1] % p)
                    u.append((u[-1] + 1) % phi_p)
                    v.append(v[-1])
                else:
                    x.append(g * x[-1] % p)
                    u.append(u[-1])
                    v.append((v[-1] + 1) % phi_p)
            elif partition == "m":
                r = x[-1] % 3
                if r == 0:
                    x.append(x[-1] ** 2 % p)
                    u.append(2 * u[-1] % phi_p)
                    v.append(2 * v[-1] % phi_p)
                elif r == 1:
                    x.append(a * x[-1] % p)
                    u.append((u[-1] + 1) % phi_p)
                    v.append(v[-1])
                else:
                    x.append(g * x[-1] % p)
                    u.append(u[-1])
                    v.append((v[-1] + 1) % phi_p)

            if i % 2 == 0 and x[i] == x[i // 2]:
                break

        b, c = u[i // 2] - u[i], v[i] - v[i // 2]
        if (b - c) % p != 0:
            log = solve_cong(b, c, phi_p)
            if log is not None and log[1] == phi_p:
                return log[0]
    
    raise ValueError("Other partition is needed.")
Esempio 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)
Esempio n. 3
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)