# builtin functions for number theory
is_prime(7) # tests whether a number is prime
# much more efficient than trial division
is_prime(23082341083410384)
is_prime(2^4219-1)
next_prime(13) # first prime bigger than n
next_prime(2^100)
randint(1,100) # generates random integer between 1,100
# NOT Cryptographically secure (but probably good enough for our purposes)
# a^e mod n
power_mod(2,5,29) # same algorithm as exp_mod that we did last class
# Diffie-Helmann key exchange
p = 1031 # common modulus to be used; this is public
# Step 1: Alice and Bob each pick secret numbers
# Alice:
a = 347 # secret, don't share with anyone
# Bob:
b = 943 # secret, don't share with anyone
# Step 2: Alice and Bob each do a computation using the secret number
# Alice:
c=power_mod(3,a,p); print(c) # 3^a mod p
# Bob:
d=power_mod(3,b,p); print(d) # 3^b mod p
# Step 3
# Alice sends c to Bob
# Bob sends d to Alice
# Eve (the eavesdropper) can see these
# Step 4: Both Alice and Bob can compute the same number, which is 3^(ab) mod p
# Alice:
KA = power_mod(d,a,p); print(KA)
# Bob:
KB = power_mod(c,b,p); print(KB)
# Why can't Eve also find K = KA = KB?
# She knows p, c = 3^a mod p, and d = 3^b mod p, since she sees the communication between Alice, Bob
# She also knows that that 3 is the base being used.
# But it is not easy to compute 3^(ab) mod p from this info.
# One approach would be to use 'brute-force' to find a, b by going through all the possiblilites and
# testing if 3^a mod p equals c for that guess of a. But there are so many possibilities
# for a that this would not be feasible.
# Fermat's little theorem:
# a^(p-1) = 1 mod p, if a is not divisible by p
power_mod(4,16,17)
power_mod(5,22,23)