use num_bigint::BigUint;
use happy_cracking::crypto::dh;
#[test]
fn test_pubkey_basic() {
let g = BigUint::from(2u32);
let p = BigUint::from(23u32);
let a = BigUint::from(6u32);
assert_eq!(
dh::compute_pubkey(&g, &a, &p).unwrap(),
BigUint::from(18u32)
);
}
#[test]
fn test_pubkey_larger() {
let g = BigUint::from(5u32);
let p = BigUint::from(23u32);
let a = BigUint::from(15u32);
let expected = g.modpow(&a, &p);
assert_eq!(dh::compute_pubkey(&g, &a, &p).unwrap(), expected);
}
#[test]
fn test_shared_secret_agreement() {
let g = BigUint::from(5u32);
let p = BigUint::from(23u32);
let a = BigUint::from(6u32);
let b = BigUint::from(15u32);
let pub_a = dh::compute_pubkey(&g, &a, &p).unwrap();
let pub_b = dh::compute_pubkey(&g, &b, &p).unwrap();
let secret_a = dh::compute_shared_secret(&pub_b, &a, &p).unwrap();
let secret_b = dh::compute_shared_secret(&pub_a, &b, &p).unwrap();
assert_eq!(secret_a, secret_b);
}
#[test]
fn test_shared_secret_larger_prime() {
let g = BigUint::from(2u32);
let p = BigUint::from(101u32);
let a = BigUint::from(37u32);
let b = BigUint::from(73u32);
let pub_a = dh::compute_pubkey(&g, &a, &p).unwrap();
let pub_b = dh::compute_pubkey(&g, &b, &p).unwrap();
let secret_a = dh::compute_shared_secret(&pub_b, &a, &p).unwrap();
let secret_b = dh::compute_shared_secret(&pub_a, &b, &p).unwrap();
assert_eq!(secret_a, secret_b);
}
#[test]
fn test_bsgs_basic() {
let g = BigUint::from(2u32);
let p = BigUint::from(29u32);
let target = BigUint::from(5u32);
let order = BigUint::from(28u32);
let x = dh::baby_step_giant_step(&g, &target, &p, &order).unwrap();
assert_eq!(g.modpow(&x, &p), target);
}
#[test]
fn test_bsgs_dlog_one() {
let g = BigUint::from(3u32);
let p = BigUint::from(17u32);
let target = BigUint::from(1u32);
let order = BigUint::from(16u32);
let x = dh::baby_step_giant_step(&g, &target, &p, &order).unwrap();
assert_eq!(g.modpow(&x, &p), target);
}
#[test]
fn test_bsgs_dlog_generator() {
let g = BigUint::from(3u32);
let p = BigUint::from(17u32);
let target = BigUint::from(3u32);
let order = BigUint::from(16u32);
let x = dh::baby_step_giant_step(&g, &target, &p, &order).unwrap();
assert_eq!(g.modpow(&x, &p), target);
}
#[test]
fn test_bsgs_ctf_scenario() {
let g = BigUint::from(2u32);
let p = BigUint::from(101u32);
let order = BigUint::from(100u32);
let secret = BigUint::from(42u32);
let pub_key = dh::compute_pubkey(&g, &secret, &p).unwrap();
let recovered = dh::baby_step_giant_step(&g, &pub_key, &p, &order).unwrap();
assert_eq!(g.modpow(&recovered, &p), pub_key);
}
#[test]
fn test_full_dh_exchange_and_break() {
let g = BigUint::from(5u32);
let p = BigUint::from(23u32);
let order = BigUint::from(22u32);
let a_priv = BigUint::from(6u32);
let b_priv = BigUint::from(15u32);
let a_pub = dh::compute_pubkey(&g, &a_priv, &p).unwrap();
let b_pub = dh::compute_pubkey(&g, &b_priv, &p).unwrap();
let shared = dh::compute_shared_secret(&b_pub, &a_priv, &p).unwrap();
let recovered_a = dh::baby_step_giant_step(&g, &a_pub, &p, &order).unwrap();
let broken_secret = dh::compute_shared_secret(&b_pub, &recovered_a, &p).unwrap();
assert_eq!(shared, broken_secret);
}
#[test]
fn test_pubkey_exponent_zero() {
let g = BigUint::from(7u32);
let p = BigUint::from(23u32);
let a = BigUint::from(0u32);
assert_eq!(dh::compute_pubkey(&g, &a, &p).unwrap(), BigUint::from(1u32));
}
#[test]
fn test_pubkey_exponent_one() {
let g = BigUint::from(7u32);
let p = BigUint::from(23u32);
let a = BigUint::from(1u32);
assert_eq!(dh::compute_pubkey(&g, &a, &p).unwrap(), BigUint::from(7u32));
}
#[test]
fn test_bsgs_order_zero() {
let g = BigUint::from(2u32);
let p = BigUint::from(23u32);
let target = BigUint::from(5u32);
let order = BigUint::from(0u32);
assert!(dh::baby_step_giant_step(&g, &target, &p, &order).is_err());
}