##########################
# SCRIPT: dh_keyexch.txt #
##########################
# Diffie-Hellman key exchange
restore  # Get previously-created parameters (p,q,g)
printf("p=%#x\n",p)
printf("q=%#x\n",q)
printf("g=%#x\n",g)

assert(p>0 and q>0 and g>0, "Failed to restore valid parameters");

puts "Validating parameters (p,q,g)"
L = 1024; M = 160 # Required bit lengths
println("bitlen(p)=",bitlen(p))
assert(bitlen(p) >= L)
puts "Checking that p is prime..."
f = isprime(p)
println("``p is prime`` is ", bool(f))
assert(f, "p is not prime")
println("bitlen(q)=",bitlen(q))
assert(bitlen(q) >= M)
f = isprime(q)
println("``q is prime`` is ", bool(f))
assert(f, "q is not prime")
f = (p-1) mod q
println("(p-1) mod q = ", f, " (expecting 0)")
assert(f==0)
println("``g < p`` is ", bool(g < p))
assert(g < p)
f = modexp(g,q,p)
println("g^q mod p = ", f, " (expecting 1)")
assert(f==1)

puts "A and B generate their private/public key pairs..."

# Party A generates a private/public key pair (x,y)
x = random(q-1)   # x in [2,(q-2)]
assert(x>1) # Chances of failure?
y = modexp(g,x,p)
printf("A's public key is %#x\n", y)

# Party B generates a private/public key pair (u,v)
u = random(q-1)
assert(u>1)
v = modexp(g,u,p)
printf("B's public key is %#x\n", v)

# Party B validates A's public key, y, and computes the common secret Z
puts "Validating A's public key, y_A..."
f = y > 1 and y < p
println("``1 < y_A <p`` is ", bool(f))
assert(f, "y_A is not valid")
z = modexp(y,u,p)
printf("Common secret computed by B, Z_B=%#x\n", z)

o = z # Remember for later

# Party A validates B's public key, v, and computes the common secret Z
puts "Validating B's public key, y_B..."
f = v > 1 and v < p
println("``1 < y_B <p`` is ", bool(f))
assert(f, "y_B is not valid")
z = modexp(v,x,p)
printf("Common secret computed by A, Z_A=%#x\n", z)

println("``Z_A == Z_B`` is ", bool(z == o))