def discrete_log(prime, public_key, primitive_root): m = int(math.floor((prime - 1) ** .5)) base_exponents = {} for j in xrange(0, m): base_exponents[fast_exponentiation(primitive_root, j, prime)] = j inverse_b = extended_euclidean_algorithm(primitive_root, prime) % prime c = fast_exponentiation(inverse_b, m, prime) x = public_key for i in xrange(0, m): if x in base_exponents: return (m * i) + base_exponents[x] else: x = (x * c) % prime
def generate_keys(): '''Alice builds a dicsrete-log public-key cipher system. ''' cyclic_group = large_random_prime() generator = random_near_primitive_root(cyclic_group) private_key = random.randint(1, cyclic_group - 1) public_key = fast_exponentiation(generator, private_key, cyclic_group) return (generator, public_key, cyclic_group), private_key
def miller_rabin(n, b): '''Miller-Rabin test for primality. ''' r = 0 m = n - 1 while m % 2 == 0: r += 1 m = m / 2 if fast_exponentiation(b, m, n) in (n - 1, 1): return True power = 1 while power < r - 1: b_m_squared_mod_n = fast_exponentiation(b, m * (2 ** power), n) if b_m_squared_mod_n == 1: return False elif b_m_squared_mod_n == n - 1: return True else: power = power * 2 return False
def test_attack_elgamal(self): #Alice p = 1009 b = 101 c = 482 l = discrete_log(prime=p, primitive_root=b, public_key=c) #Bob x = 559 r = 291 c_to_the_r = fast_exponentiation(c, r, p) encrypted_message = x * c_to_the_r % p header = fast_exponentiation(b, r, p) decrypted_message = decrypt(encrypted_message, header, l, p) print attack_elgamal(_primitive_root=b, _public_key=c, _prime=p, message=encrypted_message, header=header)
def primitive_root(group, divisors, prime): for q in divisors: if fast_exponentiation(group, (prime - 1) / q, prime) == 1: return False return True
def decrypt(message, header, l, p): c_r = fast_exponentiation(header, l, p) inverse = extended_euclidean_algorithm(c_r, p) plaintext = (inverse * message) % p return plaintext
def encrypt(message, b, c, p): r = large_random_prime() c_r = fast_exponentiation(c, r, p) encrypted_message = message * c_r % p header = fast_exponentiation(b, r, p) return encrypted_message, header
def encrypt(n, encrypt_key, message): return fast_exponentiation(message, encrypt_key, n)
def decrypt(encrypted_message, decrypt_key, n): return fast_exponentiation(encrypted_message, decrypt_key, n)