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.")
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
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)
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)