In the realm of modern cryptography, secure communication over potentially insecure channels is a crucial challenge. One of the earliest and most revolutionary breakthroughs to address this problem was the **Diffie-Hellman Key Exchange**.
It allowed two parties to create a shared secret key over a public channel without revealing that key to eavesdroppers.
Well, in my persepective the keys aren't actually "shared" in the traditional sense. You'll see what I mean by this.
## Understanding the problem
Let us assume there are 5 people standing in a line. The first person is Alice and the last person in the line is Bob. Alice wants to share a secret with Bob and the only way to communicate in this scenario is by passing the message to the person on your right(say on a piece of paper). As you may have already guessed, this poses some serious security issues since this means, everyone else in the line will find out the secret as it travels from Aice to Bob.
Although this example doesn't fully justify the state of real world insecure communication channels, you get the idea(I hope).

In reality, Alice and Bob want to a shared secret key(or encryption key) which can be used to encrypt/decrypt messages between them. Diffie Hellman solves the problem of sending these keys between 2 entities in a space full of malecious parties.
## Time for Math
* ***Step 1:*** Alice and Bob must decide on public paramters - p(base prime) and G (generator).
Let us take: $$ p = 23 $$
and: $$G = 5$$
* ***Step 2:*** Alice and Bob independently choose their private keys(not to shared with anyone)
These numbers must be in the range **1 < x < p**
Lets us say Alice: $$a = 6$$
and Bob : $$b = 15$$
* ***Step 3:*** Calculation of public keys:
For Alice: $$A = G^a mod p = 5^6 mod 23 = 8$$
For Bob: $$B = G^b mod p = 5^15 mod 23 = 19$$
* ***Step 4:*** Exchange these values over untrusted space. So now Alice has Bob's public key(B) and Bob has Alice's public key(A).
We do not care if others in the channel may have acquired these values as well.
* ***Step 5:*** Now, both Alice and Bob can compute the shared secret by raising the other’s public key to the power of their own private key, modulo p
For Alice, $$s = B^a mod p = 19^6 mod 23 = 2$$
For Bob, $$s' = A^b mod p = 8^15 mod 23 = 2$$
Hence, Alice and Bob now have a shared secret key = 2 without actually having to share the key itself.
## Time for Code
We will be using Lambdaworks which is a great library for building cryptographic primitives. Also we will be using Elliptic Curve Diffie Hellman which uses Elliptic Curves for the key generations.
In this example, we use `TinyJubJub` curve. The parameters for this curve are:
* Base Prime: p=13
* Generator: G= (10,3)
```rust
use lambdaworks_math::{cyclic_group::IsGroup,elliptic_curve::{montgomery::curves::tiny_jub_jub::{self,TinyJubJubMontgomery},traits::IsEllipticCurve}, field::element::FieldElement};
use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField;
fn main(){
tiny_jub_jub_math();
}
fn tiny_jub_jub_math(){
type BaseField=U64PrimeField<13>;
let p_x1=FieldElement::from(1);
let p_y1=FieldElement::from(9);
let p_x2=FieldElement::from(7);
let p_y2=FieldElement::from(12);
let gen=TinyJubJubMontgomery::generator();
let priv_alice=TinyJubJubMontgomery::create_point_from_affine(p_x1, p_y1).unwrap();
let priv_bob=TinyJubJubMontgomery::create_point_from_affine(p_x2, p_y2).unwrap();
//public_key= Priv_key * Generator
let pubk_alice=priv_alice.operate_with(&gen);
let pubk_bob=priv_bob.operate_with(&gen);
//secret_key_1= Priv_keyA * (Priv_keyB * Generator)
let key_alice=priv_alice.operate_with(&pubk_bob);
//secret_key_1= Priv_keyB * (Priv_keyA * Generator)
let key_bob=priv_bob.operate_with(&pubk_alice);
println!("k1:{:?}",key_alice.coordinates());
println!("k2:{:?}",key_bob.coordinates());
// Confirm K! == K2
assert_eq!(key_alice.coordinates(),key_bob.coordinates());
}
```