Path: blob/main/foundations/05-discrete-log-diffie-hellman/rust/src/lib.rs
483 views
unlisted
//! # Module 05: Discrete Logarithm and Diffie-Hellman — Exercises1//!2//! ## Progression3//! 1. `discrete_log_brute` — Scaffolded (simple loop)4//! 2. `baby_step_giant_step` — Scaffolded (HashMap hint)5//! 3. `diffie_hellman` — Independent6//! 4. `pohlig_hellman` — Independent7//! 5. `is_safe_prime` — Independent89use std::collections::HashMap;1011/// Compute discrete log by brute force: find `x` such that `g^x ≡ h (mod p)`.12///13/// Returns `None` if no solution exists within `p - 1` steps.14pub fn discrete_log_brute(g: u64, h: u64, p: u64) -> Option<u64> {15// Try x = 0, 1, 2, ... computing g^x mod p each time.16// Hint: keep a running product instead of recomputing from scratch.17todo!("Brute-force discrete log search")18}1920/// Baby-step giant-step algorithm for discrete log.21///22/// Finds `x` such that `g^x ≡ h (mod p)`, where the group order is `n`.23/// Runs in O(√n) time and space.24///25/// Algorithm:26/// m = ceil(√n)27/// Baby steps: store g^j -> j for j = 0..m28/// Giant steps: for i = 0..m, check if h * (g^(-m))^i is in the table29pub fn baby_step_giant_step(g: u64, h: u64, p: u64, n: u64) -> Option<u64> {30// Hint: use HashMap<u64, u64> for the baby step table.31// You'll need mod_inverse of g^m to compute giant steps.32todo!("BSGS discrete log in O(sqrt(n))")33}3435/// Simulate a Diffie-Hellman key exchange.36///37/// Given generator `g` and prime `p`, and two secret keys `a` and `b`:38/// Returns `(A, B, shared)` where A = g^a mod p, B = g^b mod p,39/// and shared = g^(ab) mod p.40pub fn diffie_hellman(g: u64, p: u64, a: u64, b: u64) -> (u64, u64, u64) {41todo!("DH key exchange: compute public keys and shared secret")42}4344/// Pohlig-Hellman algorithm: solve DLP when the group order factors into small primes.45///46/// Given `g^x ≡ h (mod p)` and the factorization of the group order `n = p-1`,47/// solve the DLP in each prime-power subgroup and combine with CRT.48///49/// `factors` is a list of (prime, exponent) pairs such that n = ∏ p_i^e_i.50pub fn pohlig_hellman(51g: u64,52h: u64,53p: u64,54factors: &[(u64, u32)],55) -> u64 {56todo!("Pohlig-Hellman: solve DLP via subgroup decomposition + CRT")57}5859/// Check if `p` is a safe prime: `p` is prime and `(p-1)/2` is also prime.60///61/// Safe primes resist Pohlig-Hellman because (p-1) = 2 * q where q is a large prime.62pub fn is_safe_prime(p: u64) -> bool {63todo!("Check if p and (p-1)/2 are both prime")64}6566#[cfg(test)]67mod tests {68use super::*;6970#[test]71#[ignore]72fn test_discrete_log_brute() {73// 3^x ≡ 6 (mod 7). Answer: x = 3 (3^3 = 27 ≡ 6)74assert_eq!(discrete_log_brute(3, 6, 7), Some(3));75}7677#[test]78#[ignore]79fn test_discrete_log_brute_identity() {80// g^0 = 1 for any g81assert_eq!(discrete_log_brute(5, 1, 13), Some(0));82}8384#[test]85#[ignore]86fn test_bsgs() {87// 2^x ≡ 3 (mod 5), order 4. Answer: x = 388assert_eq!(baby_step_giant_step(2, 3, 5, 4), Some(3));89}9091#[test]92#[ignore]93fn test_diffie_hellman() {94let (big_a, big_b, shared) = diffie_hellman(5, 23, 6, 15);95assert_eq!(big_a, 8); // 5^6 mod 2396assert_eq!(big_b, 19); // 5^15 mod 2397// Both sides compute the same shared secret98// A^b = 8^15 mod 23 = B^a = 19^6 mod 2399assert_eq!(shared, 2);100}101102#[test]103#[ignore]104fn test_is_safe_prime() {105assert!(is_safe_prime(23)); // (23-1)/2 = 11, both prime106assert!(!is_safe_prime(37)); // (37-1)/2 = 18, not prime107}108}109110111