Exemple #1
0
    def crack(cls, m: "iterable of ints", c: "iterable of ints", p: int):
        """ Attempts to recreate the key based on the message m and
            its encryption c assuming the modulus is p. """
        sizes = (d for d in divisors(len(m)) if d**2 + d <= len(m))
        for size in sizes:
            M = np.reshape(m, (size, -1), order="F")
            C = np.reshape(c, (size, -1), order="F")
            m0, c0 = M[:, [0]], C[:, [0]]
            vecs = (M - m0) % p
            vals = (C - c0) % p

            start = 1
            P = vecs[:, start:(start + size)]
            while det(P, p) == 0:
                start += 1
                P = vecs[:, start:(start + size)]
            P_inv = mat_inverse(P, p)

            corr_vals = vals[:, start:(start + size)]
            K1 = corr_vals.dot(P_inv) % p
            K2 = (c0 - K1.dot(m0)) % p

            if ((K1.dot(M) + K2) % p == C).all():
                return cls(K1, K2, p)

        raise ValueError("Not enough information.")
Exemple #2
0
 def crack(cls, e: str):
     """ Loops over all possible transpositions of the encrypted
         text e. It's up to the user to decide when the cipher is
         broken - then type any character and press enter. """
     for line_len in divisors(len(e)):
         cipher = cls(line_len)
         if input(cipher.cipher(e)):
             break
     else:
         raise ValueError("Possibilities exhausted.")
     return cipher
Exemple #3
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)
Exemple #4
0
def order(a, n):
    """ Computes order of a modulo n. """
    return min(d for d in divisors(carmichael(n)) if pow(a, d, n) == 1)