Path: blob/main/foundations/06-elliptic-curves/rust/src/lib.rs
483 views
unlisted
//! # Module 06: Elliptic Curves — Exercises1//!2//! All curves are in short Weierstrass form: y² = x³ + ax + b over GF(p).3//!4//! ## Progression5//! 1. `point_add` — Scaffolded (formulas in doc)6//! 2. `point_double` — Scaffolded (tangent formula)7//! 3. `scalar_mul` — Independent (double-and-add)8//! 4. `ecdh_shared_secret` — Independent9//! 5. `ecdsa_verify` — Independent1011/// A point on an elliptic curve, or the point at infinity.12#[derive(Debug, Clone, Copy, PartialEq, Eq)]13pub enum Point {14/// The identity element (point at infinity).15Infinity,16/// An affine point (x, y).17Affine(i64, i64),18}1920/// Curve parameters: y² = x³ + ax + b (mod p).21#[derive(Debug, Clone, Copy)]22pub struct CurveParams {23pub a: i64,24pub b: i64,25pub p: i64,26}2728/// Add two points on the curve.29///30/// Formulas (when P ≠ Q, neither is infinity):31/// λ = (y₂ - y₁) / (x₂ - x₁) mod p32/// x₃ = λ² - x₁ - x₂ mod p33/// y₃ = λ(x₁ - x₃) - y₁ mod p34///35/// Handle special cases: infinity, same point (use `point_double`),36/// vertical line (x₁ = x₂, y₁ = -y₂ → Infinity).37pub fn point_add(p1: Point, p2: Point, curve: &CurveParams) -> Point {38todo!("Elliptic curve point addition")39}4041/// Double a point on the curve.42///43/// Formula (when P is not infinity and y ≠ 0):44/// λ = (3x² + a) / (2y) mod p45/// x₃ = λ² - 2x mod p46/// y₃ = λ(x - x₃) - y mod p47pub fn point_double(p: Point, curve: &CurveParams) -> Point {48todo!("Elliptic curve point doubling")49}5051/// Scalar multiplication: compute `k * P` using double-and-add.52pub fn scalar_mul(k: u64, p: Point, curve: &CurveParams) -> Point {53todo!("Double-and-add scalar multiplication")54}5556/// Compute ECDH shared secret: `sk * other_public_key`.57pub fn ecdh_shared_secret(sk: u64, pk: Point, curve: &CurveParams) -> Point {58todo!("ECDH: scalar_mul(sk, pk)")59}6061/// Verify an ECDSA signature.62///63/// Given message hash `z`, signature `(r, s)`, public key `pk`,64/// generator `g` with order `n`:65/// w = s^(-1) mod n66/// u1 = z * w mod n67/// u2 = r * w mod n68/// R = u1*G + u2*pk69/// valid iff R.x ≡ r (mod n)70pub fn ecdsa_verify(71z: u64,72r: u64,73s: u64,74pk: Point,75g: Point,76n: u64,77curve: &CurveParams,78) -> bool {79todo!("ECDSA signature verification")80}8182/// Helper: compute modular inverse using Fermat's little theorem.83/// Only works when `p` is prime: a^(-1) = a^(p-2) mod p.84fn mod_inv(a: i64, p: i64) -> i64 {85mod_pow(a.rem_euclid(p), (p - 2) as u64, p)86}8788/// Helper: modular exponentiation for i64 values.89fn mod_pow(mut base: i64, mut exp: u64, modulus: i64) -> i64 {90let mut result = 1i64;91base = base.rem_euclid(modulus);92while exp > 0 {93if exp % 2 == 1 {94result = (result as i128 * base as i128).rem_euclid(modulus as i128) as i64;95}96exp /= 2;97base = (base as i128 * base as i128).rem_euclid(modulus as i128) as i64;98}99result100}101102#[cfg(test)]103mod tests {104use super::*;105106fn test_curve() -> CurveParams {107// y² = x³ + 2x + 3 over GF(97)108CurveParams { a: 2, b: 3, p: 97 }109}110111#[test]112#[ignore]113fn test_point_add_basic() {114let c = test_curve();115let p1 = Point::Affine(3, 6);116let p2 = Point::Affine(80, 10);117let sum = point_add(p1, p2, &c);118// Verify the result is on the curve119if let Point::Affine(x, y) = sum {120let lhs = (y * y).rem_euclid(c.p);121let rhs = (x * x * x + c.a * x + c.b).rem_euclid(c.p);122assert_eq!(lhs, rhs, "Result should be on the curve");123}124}125126#[test]127#[ignore]128fn test_point_add_infinity() {129let c = test_curve();130let p1 = Point::Affine(3, 6);131assert_eq!(point_add(p1, Point::Infinity, &c), p1);132assert_eq!(point_add(Point::Infinity, p1, &c), p1);133}134135#[test]136#[ignore]137fn test_point_double() {138let c = test_curve();139let p1 = Point::Affine(3, 6);140let doubled = point_double(p1, &c);141if let Point::Affine(x, y) = doubled {142let lhs = (y * y).rem_euclid(c.p);143let rhs = (x * x * x + c.a * x + c.b).rem_euclid(c.p);144assert_eq!(lhs, rhs, "Doubled point should be on the curve");145}146}147148#[test]149#[ignore]150fn test_scalar_mul_identity() {151let c = test_curve();152let p1 = Point::Affine(3, 6);153assert_eq!(scalar_mul(1, p1, &c), p1);154}155156#[test]157#[ignore]158fn test_ecdh() {159let c = test_curve();160let g = Point::Affine(3, 6);161let (a, b) = (7_u64, 11_u64);162let pk_a = scalar_mul(a, g, &c);163let pk_b = scalar_mul(b, g, &c);164let shared_a = ecdh_shared_secret(a, pk_b, &c);165let shared_b = ecdh_shared_secret(b, pk_a, &c);166assert_eq!(shared_a, shared_b, "Both parties should derive same shared secret");167}168}169170171