Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
duyuefeng0708
GitHub Repository: duyuefeng0708/Cryptography-From-First-Principle
Path: blob/main/foundations/06-elliptic-curves/rust/src/lib.rs
483 views
unlisted
1
//! # Module 06: Elliptic Curves — Exercises
2
//!
3
//! All curves are in short Weierstrass form: y² = x³ + ax + b over GF(p).
4
//!
5
//! ## Progression
6
//! 1. `point_add` — Scaffolded (formulas in doc)
7
//! 2. `point_double` — Scaffolded (tangent formula)
8
//! 3. `scalar_mul` — Independent (double-and-add)
9
//! 4. `ecdh_shared_secret` — Independent
10
//! 5. `ecdsa_verify` — Independent
11
12
/// A point on an elliptic curve, or the point at infinity.
13
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14
pub enum Point {
15
/// The identity element (point at infinity).
16
Infinity,
17
/// An affine point (x, y).
18
Affine(i64, i64),
19
}
20
21
/// Curve parameters: y² = x³ + ax + b (mod p).
22
#[derive(Debug, Clone, Copy)]
23
pub struct CurveParams {
24
pub a: i64,
25
pub b: i64,
26
pub p: i64,
27
}
28
29
/// Add two points on the curve.
30
///
31
/// Formulas (when P ≠ Q, neither is infinity):
32
/// λ = (y₂ - y₁) / (x₂ - x₁) mod p
33
/// x₃ = λ² - x₁ - x₂ mod p
34
/// y₃ = λ(x₁ - x₃) - y₁ mod p
35
///
36
/// Handle special cases: infinity, same point (use `point_double`),
37
/// vertical line (x₁ = x₂, y₁ = -y₂ → Infinity).
38
pub fn point_add(p1: Point, p2: Point, curve: &CurveParams) -> Point {
39
todo!("Elliptic curve point addition")
40
}
41
42
/// Double a point on the curve.
43
///
44
/// Formula (when P is not infinity and y ≠ 0):
45
/// λ = (3x² + a) / (2y) mod p
46
/// x₃ = λ² - 2x mod p
47
/// y₃ = λ(x - x₃) - y mod p
48
pub fn point_double(p: Point, curve: &CurveParams) -> Point {
49
todo!("Elliptic curve point doubling")
50
}
51
52
/// Scalar multiplication: compute `k * P` using double-and-add.
53
pub fn scalar_mul(k: u64, p: Point, curve: &CurveParams) -> Point {
54
todo!("Double-and-add scalar multiplication")
55
}
56
57
/// Compute ECDH shared secret: `sk * other_public_key`.
58
pub fn ecdh_shared_secret(sk: u64, pk: Point, curve: &CurveParams) -> Point {
59
todo!("ECDH: scalar_mul(sk, pk)")
60
}
61
62
/// Verify an ECDSA signature.
63
///
64
/// Given message hash `z`, signature `(r, s)`, public key `pk`,
65
/// generator `g` with order `n`:
66
/// w = s^(-1) mod n
67
/// u1 = z * w mod n
68
/// u2 = r * w mod n
69
/// R = u1*G + u2*pk
70
/// valid iff R.x ≡ r (mod n)
71
pub fn ecdsa_verify(
72
z: u64,
73
r: u64,
74
s: u64,
75
pk: Point,
76
g: Point,
77
n: u64,
78
curve: &CurveParams,
79
) -> bool {
80
todo!("ECDSA signature verification")
81
}
82
83
/// Helper: compute modular inverse using Fermat's little theorem.
84
/// Only works when `p` is prime: a^(-1) = a^(p-2) mod p.
85
fn mod_inv(a: i64, p: i64) -> i64 {
86
mod_pow(a.rem_euclid(p), (p - 2) as u64, p)
87
}
88
89
/// Helper: modular exponentiation for i64 values.
90
fn mod_pow(mut base: i64, mut exp: u64, modulus: i64) -> i64 {
91
let mut result = 1i64;
92
base = base.rem_euclid(modulus);
93
while exp > 0 {
94
if exp % 2 == 1 {
95
result = (result as i128 * base as i128).rem_euclid(modulus as i128) as i64;
96
}
97
exp /= 2;
98
base = (base as i128 * base as i128).rem_euclid(modulus as i128) as i64;
99
}
100
result
101
}
102
103
#[cfg(test)]
104
mod tests {
105
use super::*;
106
107
fn test_curve() -> CurveParams {
108
// y² = x³ + 2x + 3 over GF(97)
109
CurveParams { a: 2, b: 3, p: 97 }
110
}
111
112
#[test]
113
#[ignore]
114
fn test_point_add_basic() {
115
let c = test_curve();
116
let p1 = Point::Affine(3, 6);
117
let p2 = Point::Affine(80, 10);
118
let sum = point_add(p1, p2, &c);
119
// Verify the result is on the curve
120
if let Point::Affine(x, y) = sum {
121
let lhs = (y * y).rem_euclid(c.p);
122
let rhs = (x * x * x + c.a * x + c.b).rem_euclid(c.p);
123
assert_eq!(lhs, rhs, "Result should be on the curve");
124
}
125
}
126
127
#[test]
128
#[ignore]
129
fn test_point_add_infinity() {
130
let c = test_curve();
131
let p1 = Point::Affine(3, 6);
132
assert_eq!(point_add(p1, Point::Infinity, &c), p1);
133
assert_eq!(point_add(Point::Infinity, p1, &c), p1);
134
}
135
136
#[test]
137
#[ignore]
138
fn test_point_double() {
139
let c = test_curve();
140
let p1 = Point::Affine(3, 6);
141
let doubled = point_double(p1, &c);
142
if let Point::Affine(x, y) = doubled {
143
let lhs = (y * y).rem_euclid(c.p);
144
let rhs = (x * x * x + c.a * x + c.b).rem_euclid(c.p);
145
assert_eq!(lhs, rhs, "Doubled point should be on the curve");
146
}
147
}
148
149
#[test]
150
#[ignore]
151
fn test_scalar_mul_identity() {
152
let c = test_curve();
153
let p1 = Point::Affine(3, 6);
154
assert_eq!(scalar_mul(1, p1, &c), p1);
155
}
156
157
#[test]
158
#[ignore]
159
fn test_ecdh() {
160
let c = test_curve();
161
let g = Point::Affine(3, 6);
162
let (a, b) = (7_u64, 11_u64);
163
let pk_a = scalar_mul(a, g, &c);
164
let pk_b = scalar_mul(b, g, &c);
165
let shared_a = ecdh_shared_secret(a, pk_b, &c);
166
let shared_b = ecdh_shared_secret(b, pk_a, &c);
167
assert_eq!(shared_a, shared_b, "Both parties should derive same shared secret");
168
}
169
}
170
171