def pollards(N, attempts=100, a_max=13): # We seek p, q such that pq = N # We notice that a^(p-1)i = 1 modulo p for all integers i # and that it is rather unlikely that a^(p-1)i = 1 modulo q # We see that this statement is equivalent to: # "p divides a^(p-1)i-1, but q probably does not divide a^(p-1)i-1" # We therefore seek L such that p divides a^L - 1, but q does not divide A^L-1 # If p-1 is a product of small prime, we will probably discover p-1 | n! for some small n # Therefore, we realise that, if p-1 is the product of small primes, a suitable L is n! for some small n for a in range(2, a_max + 1): trial_L = 1 trial = 1 for i in range(1, attempts): trial_L *= i trial_L %= N trial **= (N - 1) trial = pow(a, trial_L, N) - 1 if trial < 1: trial += N gcd = euclids_gcd(N, trial) if (gcd == N): break if (gcd != 1): return (gcd, N / gcd)
def naive_difference_of_squares_factorization(n, outer_depth=1000, inner_depth=1000, verbose=False): is_square = lambda x, float_precision=1e-12: int(x**.5 + float_precision )**2 == x k = 1 if n == 1 or is_prime(n): return [n] for _ in range(outer_depth): k += 1 if not n % 2 else 2 for b in range(inner_depth): if is_square(k * n + b**2): a = int(round((k * n + b**2)**.5)) f1 = euclids_gcd(n, a + b) f2 = euclids_gcd(n, a - b) if (f1 in [1, n]) and (f2 in [1, n]): continue elif (f1 in [1, n]): f1 = n / f2 elif (f2 in [1, n]): f2 = n / f1 elif f1 * f2 != n: f1 = max(f1, f2) f2 = n / f1 if verbose: print str(n) + " => " + str([f1, f2]) return sorted( naive_difference_of_squares_factorization(f1) + naive_difference_of_squares_factorization(f2)) # No solution found in given depth return [n]
def generate_public_key(self): # Find suitable primes p, and q if 'p' in self.configuration: self.p = self.configuration['p'] else: while True: self.p = random.randrange( 2, 2 << (self.configuration['width'] >> 1)) if is_prime(self.p): break if 'q' in self.configuration: self.q = self.configuration['q'] else: while True: self.q = random.randrange( 2, 2 << (self.configuration['width'] >> 1)) if is_prime(self.q): break self.pq = self.p * self.q # Find a suitable exponent e if 'e' in self.configuration: self.e = self.configuration['e'] else: while True: self.e = random.randrange(2, 2 << (self.configuration['width'])) if euclids_gcd(self.e, (self.p - 1) * (self.q - 1)) == 1: break # We now have all the pieces for our public key self.public_key = (self.pq, self.e) # Solve for inverse of e self.d = extended_euclids_gcd(self.e, (self.p - 1) * (self.q - 1))[1] if self.d < 0: self.d += (self.p - 1) * (self.q - 1)
def sign(self, document, hashing=True): hashed_document = self.hash_document(document) while True: k = random.randrange(2, self.p - 1) if euclids_gcd(k, self.p - 1) == 1: break s1 = fast_powering(self.g, k, self.p) s2 = ((hashed_document - self.private_key * s1) * extended_euclidean_inverse(k, self.p - 1)) % (self.p - 1) return (s1, s2)
def miller_rabin(n, a): # True implies n is composite from gcd import euclids_gcd # Test if n is even if not (n & 1): return True # Test if a divides n gcd = euclids_gcd(n, a) if (1 < gcd) and (gcd < n): return True # Find q such that n - 1 = 2^k q q = n - 1 k = 0 while not (q & 1): q >>= 1 k += 1 # Search for the existence of i such that a^( (2^i) q ) = -1 (mod p), i < k a = pow(a, q, n) if a == 1: return False for i in range(k): if a == n - 1: return False a = pow(a, 2, n) return True