clock_curve_math/field/elliptic_curve.rs
1//! Elliptic curve arithmetic for cryptographic curve types.
2//!
3//! This module implements elliptic curve group operations for different curve models
4//! used in public-key cryptography. Elliptic curves provide the mathematical foundation
5//! for ECDSA signatures, ECDH key exchange, and other cryptographic protocols.
6//!
7//! # Supported Curve Models
8//!
9//! ## Weierstrass Curves
10//! Standard curve representation: `y² = x³ + ax + b`
11//! - Used by secp256k1 (Bitcoin), NIST P-curves
12//! - Point addition and doubling use chord-tangent formulas
13//! - Point at infinity represented as (0,0)
14//!
15//! ## Edwards Curves
16//! Twisted Edwards form: `ax² + y² = 1 + dx²y²`
17//! - Used by Ed25519, Curve25519
18//! - Unified addition formulas (resistant to some attacks)
19//! - Complete addition formulas (no exceptional cases)
20//!
21//! # Cryptographic Operations
22//!
23//! ## Point Addition
24//! Combines two curve points using the curve's group law:
25//! - **Weierstrass**: Complex formulas with special cases for doubling
26//! - **Edwards**: Unified formulas work for all point combinations
27//!
28//! ## Scalar Multiplication
29//! Computes `k * P` for scalar k and point P:
30//! - Uses Montgomery ladder for constant-time execution
31//! - Prevents timing attacks on secret scalars
32//! - Fundamental operation for ECDSA and ECDH
33//!
34//! ## Point Validation
35//! Verifies points lie on the curve:
36//! - Prevents invalid point attacks
37//! - Ensures mathematical consistency
38//! - Critical for protocol security
39//!
40//! # Security Considerations
41//!
42//! ## Constant-Time Operations
43//! All curve operations execute in constant time to prevent:
44//! - **Timing attacks**: Measuring operation time to recover keys
45//! - **Cache attacks**: Observing memory access patterns
46//! - **Branch prediction attacks**: Analyzing control flow
47//!
48//! ## Mathematical Correctness
49//! Operations maintain curve invariants:
50//! - Points remain on the curve after operations
51//! - Group law is preserved
52//! - Scalar multiplication is correct
53//!
54//! ## Side-Channel Resistance
55//! Implementation designed to prevent:
56//! - Power analysis attacks
57//! - Electromagnetic analysis
58//! - Fault injection attacks
59//!
60//! # Performance Characteristics
61//!
62//! ## Operation Complexity
63//! - **Point Addition**: O(1) field operations
64//! - **Point Doubling**: O(1) field operations
65//! - **Scalar Multiplication**: O(log scalar) point operations
66//! - **Point Validation**: O(1) field operations
67//!
68//! ## Curve-Specific Optimizations
69//! - **Edwards curves**: Faster addition due to unified formulas
70//! - **Weierstrass curves**: Optimized doubling for scalar multiplication
71//! - **Montgomery ladder**: Constant-time scalar multiplication
72//!
73//! # Usage Examples
74//!
75//! ## Basic Point Operations
76//! ```ignore
77//! use clock_curve_math::field::elliptic_curve::*;
78//!
79//! // Create curve and points
80//! let curve = secp256k1_curve();
81//! let p1 = (FieldElement::from_u64(1), FieldElement::from_u64(2));
82//! let p2 = (FieldElement::from_u64(3), FieldElement::from_u64(4));
83//!
84//! // Point addition
85//! let sum = point_add(&p1, &p2, curve);
86//!
87//! // Scalar multiplication
88//! let scalar = BigInt::from_u64(42);
89//! let result = scalar_mul(&p1, &scalar, curve);
90//!
91//! // Point validation
92//! assert!(is_on_curve(&sum, curve));
93//! ```
94//!
95//! ## Cryptographic Protocols
96//! ```ignore
97//! // ECDSA signature generation (simplified)
98//! let private_key = BigInt::from_bytes(&private_key_bytes);
99//! let message_hash = BigInt::from_bytes(&hash_bytes);
100//!
101//! // R = k * G (generator point)
102//! let r_point = scalar_mul(&generator, &k, curve);
103//! let r = r_point.0; // x-coordinate
104//!
105//! // s = k⁻¹ * (hash + r * private_key) mod order
106//! let s = compute_signature_s(&k_inv, &message_hash, &r, &private_key);
107//!
108//! let signature = (r, s);
109//! ```
110//!
111//! # Implementation Notes
112//!
113//! ## Point at Infinity
114//! Represented as (0,0) for both curve types, though this is not a valid curve point.
115//! Addition with infinity returns the other point, maintaining group properties.
116//!
117//! ## Field Operations
118//! All curve arithmetic delegates to the underlying finite field implementation,
119//! ensuring constant-time execution and mathematical correctness.
120//!
121//! ## Error Handling
122//! Functions assume valid inputs (points on curve, valid scalars).
123//! Invalid inputs may produce incorrect results or panics.
124//! Input validation should be performed by calling code.
125//!
126//! ## Standardization
127//! Implements standard curve parameters:
128//! - **Ed25519**: a = -1, d computed from curve constants
129//! - **secp256k1**: a = 0, b = 7 (simplified field representation)
130
131use crate::field::{FieldElement, FieldOps};
132
133/// Elliptic curve type enumeration defining supported curve models.
134///
135/// This enum represents the two main families of elliptic curves used in cryptography,
136/// each with different mathematical properties and performance characteristics.
137/// The choice of curve model affects implementation complexity, performance, and
138/// security properties.
139///
140/// # Mathematical Foundations
141///
142/// ## Weierstrass Curves
143/// **Equation**: `y² = x³ + ax + b`
144///
145/// Classic curve representation used by most standardized curves including:
146/// - NIST P-curves (P-256, P-384, P-521)
147/// - secp256k1 (Bitcoin curve)
148/// - Brainpool curves
149///
150/// **Properties**:
151/// - Point addition requires case analysis (doubling vs. addition)
152/// - Point at infinity requires special handling
153/// - More complex implementation but widely supported
154///
155/// ## Edwards Curves
156/// **Equation**: `ax² + y² = 1 + dx²y²` (twisted Edwards form)
157///
158/// Modern curve representation with better properties:
159/// - Ed25519 (digital signatures)
160/// - Curve25519 (key exchange)
161/// - More recent standardized curves
162///
163/// **Properties**:
164/// - Unified addition formulas (no special cases)
165/// - Complete formulas (no exceptional points)
166/// - Faster arithmetic, simpler implementation
167/// - Better resistance to some implementation attacks
168///
169/// # Security Considerations
170///
171/// ## Implementation Attacks
172/// - **Edwards curves**: More resistant to timing attacks due to unified formulas
173/// - **Weierstrass curves**: Require careful handling of point doubling cases
174///
175/// ## Side-Channel Resistance
176/// - Both models can be implemented with constant-time arithmetic
177/// - Edwards curves have simpler control flow
178/// - Choice affects cache access patterns and power consumption
179///
180/// # Performance Characteristics
181///
182/// ## Addition Speed
183/// - **Edwards**: Faster due to unified formulas
184/// - **Weierstrass**: Slightly slower due to case analysis
185///
186/// ## Implementation Complexity
187/// - **Edwards**: Simpler code, fewer edge cases
188/// - **Weierstrass**: More complex, more special cases
189///
190/// ## Memory Usage
191/// - Both models use similar memory for point operations
192/// - Curve parameters (a,b,d) stored in enum variants
193///
194/// # Usage Examples
195///
196/// ```ignore
197/// use clock_curve_math::field::elliptic_curve::CurveType;
198///
199/// // secp256k1 (Bitcoin curve)
200/// let secp256k1 = CurveType::Weierstrass {
201/// a: FieldElement::from_u64(0),
202/// b: FieldElement::from_u64(7),
203/// };
204///
205/// // Ed25519 curve
206/// let ed25519 = CurveType::Edwards {
207/// a: FieldElement::from_u64(0).sub(&FieldElement::from_u64(1)), // a = -1
208/// d: /* computed d parameter */,
209/// };
210/// ```
211///
212/// # Conversion Between Models
213///
214/// Some curves can be represented in both forms:
215/// - **Curve25519**: Can be converted between Montgomery and Edwards forms
216/// - **secp256k1**: Weierstrass form only
217/// - **NIST P-256**: Weierstrass form only
218///
219/// The enum prevents mixing operations between incompatible curve types.
220#[derive(Clone, Copy, Debug)]
221pub enum CurveType {
222 /// Weierstrass curve model: y² = x³ + ax + b
223 ///
224 /// The classical elliptic curve representation used by most standardized
225 /// cryptographic curves. Point arithmetic uses chord-tangent formulas
226 /// with special cases for point doubling.
227 ///
228 /// # Parameters
229 /// - `a`: Linear coefficient in the curve equation
230 /// - `b`: Constant term in the curve equation
231 ///
232 /// # Examples
233 /// - secp256k1: a=0, b=7
234 /// - NIST P-256: a=-3, b=constant
235 Weierstrass {
236 /// Coefficient 'a' in the curve equation y² = x³ + ax + b
237 a: FieldElement,
238 /// Coefficient 'b' in the curve equation y² = x³ + ax + b
239 b: FieldElement,
240 },
241
242 /// Edwards curve model: ax² + y² = 1 + dx²y²
243 ///
244 /// Modern elliptic curve representation with unified addition formulas
245 /// that work for all point combinations without special cases. Provides
246 /// better performance and security properties than Weierstrass curves.
247 ///
248 /// # Parameters
249 /// - `a`: Coefficient in the x² term
250 /// - `d`: Coefficient in the x²y² term
251 ///
252 /// # Examples
253 /// - Ed25519: a=-1, d=specific constant
254 /// - Curve25519: a=constant, d=constant
255 Edwards {
256 /// Coefficient 'a' in the Edwards equation ax² + y² = 1 + dx²y²
257 a: FieldElement,
258 /// Coefficient 'd' in the Edwards equation ax² + y² = 1 + dx²y²
259 d: FieldElement,
260 },
261}
262
263/// Extended Edwards curve point representation.
264///
265/// Uses extended coordinates (X:Y:Z:T) where T = X·Y·Z⁻¹.
266/// This representation is optimized for Edwards curve arithmetic and enables
267/// faster point addition and doubling operations.
268///
269/// The curve equation in extended coordinates becomes:
270/// X² + Y² = Z² + d·X²·Y²
271///
272/// # Coordinate Meaning
273/// - `x`: X-coordinate in extended form
274/// - `y`: Y-coordinate in extended form
275/// - `z`: Z-coordinate (denominator)
276/// - `t`: T-coordinate where T = X·Y·Z⁻¹
277///
278/// # Security
279/// All operations are constant-time to prevent timing attacks.
280/// Point validation methods ensure mathematical consistency.
281#[derive(Clone, Copy, Debug, PartialEq, Eq)]
282pub struct ExtendedPoint {
283 /// X-coordinate
284 pub x: FieldElement,
285 /// Y-coordinate
286 pub y: FieldElement,
287 /// Z-coordinate (denominator)
288 pub z: FieldElement,
289 /// T-coordinate where T = X·Y·Z⁻¹
290 pub t: FieldElement,
291}
292
293impl ExtendedPoint {
294 /// Create a new extended point with the given coordinates.
295 ///
296 /// # Warning
297 /// This constructor does not validate that the point satisfies the curve equation.
298 /// Use `is_on_curve()` to verify the point is valid.
299 pub fn new(x: FieldElement, y: FieldElement, z: FieldElement, t: FieldElement) -> Self {
300 Self { x, y, z, t }
301 }
302
303 /// Create the identity element (point at infinity).
304 ///
305 /// In extended coordinates, the point at infinity is represented as (0,1,1,0).
306 pub fn identity() -> Self {
307 Self {
308 x: FieldElement::from_u64(0),
309 y: FieldElement::from_u64(1),
310 z: FieldElement::from_u64(1),
311 t: FieldElement::from_u64(0),
312 }
313 }
314
315 /// Create a point from affine coordinates (x, y).
316 ///
317 /// Converts (x, y) to extended coordinates (x, y, 1, x*y).
318 /// This assumes the affine point is already on the curve.
319 pub fn from_affine(x: FieldElement, y: FieldElement) -> Self {
320 Self {
321 x,
322 y,
323 z: FieldElement::from_u64(1),
324 t: x.mul(&y),
325 }
326 }
327
328 /// Constant-time conditional selection between two extended points.
329 ///
330 /// Returns `a` if `choice` is true, otherwise returns `b`.
331 /// This operation executes in constant time regardless of the choice value.
332 ///
333 /// # Parameters
334 /// * `a` - First point (selected when choice is true)
335 /// * `b` - Second point (selected when choice is false)
336 /// * `choice` - Selection choice
337 ///
338 /// # Returns
339 /// The selected point based on the choice
340 ///
341 /// # Security
342 /// This function is constant-time and safe for cryptographic use with secret choices.
343 pub fn conditional_select(a: &Self, b: &Self, choice: crate::ct::Choice) -> Self {
344 Self {
345 x: FieldElement::conditional_select(&a.x, &b.x, choice),
346 y: FieldElement::conditional_select(&a.y, &b.y, choice),
347 z: FieldElement::conditional_select(&a.z, &b.z, choice),
348 t: FieldElement::conditional_select(&a.t, &b.t, choice),
349 }
350 }
351
352 /// Check if this point satisfies the extended coordinate invariant T = X·Y·Z⁻¹.
353 ///
354 /// This validates the internal consistency of the extended point representation,
355 /// but does not check if the point lies on the curve.
356 ///
357 /// # Returns
358 /// `true` if the point coordinates are consistent, `false` otherwise
359 ///
360 /// # Mathematical Check
361 /// Verifies: T * Z ≡ X * Y mod p
362 pub fn is_valid(&self) -> bool {
363 if self.z.is_zero() {
364 // Z = 0 is invalid (would cause division by zero)
365 return false;
366 }
367
368 // Check T * Z == X * Y mod p
369 let left = self.t.mul(&self.z);
370 let right = self.x.mul(&self.y);
371 left == right
372 }
373
374 /// Check if this point lies on the specified Edwards curve.
375 ///
376 /// Verifies that the point satisfies the Edwards curve equation:
377 /// -x² + y² = 1 + d·x²·y²
378 ///
379 /// This converts the point to affine coordinates first, then checks the equation.
380 /// Points with Z = 0 are considered invalid and return false.
381 ///
382 /// # Parameters
383 /// * `curve` - The curve parameters defining the equation to check
384 ///
385 /// # Returns
386 /// `true` if the point lies on the curve, `false` otherwise
387 pub fn is_on_curve(&self, curve: CurveType) -> bool {
388 // Check if point is valid first
389 if !self.is_valid() {
390 return false;
391 }
392
393 match curve {
394 CurveType::Edwards { a: _, d } => self.is_on_edwards_curve(d),
395 CurveType::Weierstrass { .. } => {
396 // Convert to affine and check Weierstrass equation
397 let affine = self.to_affine();
398 is_on_curve(&affine, curve)
399 }
400 }
401 }
402
403 /// Check if this point lies on an Edwards curve with parameter d.
404 ///
405 /// Verifies: -x² + y² = 1 + d·x²·y²
406 ///
407 /// # Parameters
408 /// * `d` - The Edwards curve parameter
409 ///
410 /// # Returns
411 /// `true` if the point satisfies the Edwards equation
412 ///
413 /// # Note
414 /// This method assumes the point is valid (Z ≠ 0). Call `is_valid()` first.
415 fn is_on_edwards_curve(&self, d: FieldElement) -> bool {
416 // Convert to affine coordinates
417 let z_inv = self.z.inv();
418 let x_affine = self.x.mul(&z_inv);
419 let y_affine = self.y.mul(&z_inv);
420
421 // Check Edwards equation: -x² + y² = 1 + d·x²·y²
422 let x2 = x_affine.square();
423 let y2 = y_affine.square();
424 let xy2 = x2.mul(&y2);
425
426 let left = y2.sub(&x2);
427 let right = FieldElement::from_u64(1).add(&d.mul(&xy2));
428
429 left == right
430 }
431
432 /// Convert this extended point to affine coordinates (x/z, y/z).
433 ///
434 /// # Returns
435 /// A tuple (x, y) representing the affine coordinates
436 ///
437 /// # Panics
438 /// Panics if Z = 0 (point at infinity or invalid representation)
439 pub fn to_affine(&self) -> (FieldElement, FieldElement) {
440 if self.z.is_zero() {
441 panic!("Cannot convert point at infinity to affine coordinates");
442 }
443
444 let z_inv = self.z.inv();
445 let x_affine = self.x.mul(&z_inv);
446 let y_affine = self.y.mul(&z_inv);
447
448 (x_affine, y_affine)
449 }
450
451 /// Check if this point is the identity element (point at infinity).
452 ///
453 /// In extended coordinates, the identity is represented as (0,1,1,0).
454 pub fn is_identity(&self) -> bool {
455 self.x.is_zero() && self.y == FieldElement::from_u64(1) &&
456 self.z == FieldElement::from_u64(1) && self.t.is_zero()
457 }
458
459 /// Add two extended points on an Edwards curve.
460 ///
461 /// Uses the complete extended Edwards addition formulas that work for all
462 /// point combinations without special cases. This is more efficient than
463 /// converting to affine coordinates first.
464 ///
465 /// # Parameters
466 /// * `other` - The point to add to this point
467 /// * `curve` - The curve parameters defining the addition operation
468 ///
469 /// # Returns
470 /// The sum of the two points in extended coordinates
471 pub fn add(&self, other: &Self, curve: CurveType) -> Self {
472 match curve {
473 CurveType::Edwards { a, d } => self.add_edwards(other, a, d),
474 CurveType::Weierstrass { .. } => {
475 // For Weierstrass curves, convert to affine, add, then back to extended
476 let p1_affine = self.to_affine();
477 let p2_affine = other.to_affine();
478 let sum_affine = point_add(&p1_affine, &p2_affine, curve);
479 Self::from_affine(sum_affine.0, sum_affine.1)
480 }
481 }
482 }
483
484 /// Add two points on an Edwards curve using extended coordinates.
485 ///
486 /// Uses the complete extended Edwards addition formulas:
487 /// X3 = (X1·Y2 + Y1·X2) · (Z1·Z2 - d·T1·T2)
488 /// Y3 = (Y1·Y2 - a·X1·X2) · (Z1·Z2 + d·T1·T2)
489 /// Z3 = (Z1·Z2 - d·T1·T2) · (Z1·Z2 + d·T1·T2)
490 /// T3 = (X1·Y2 + Y1·X2) · (Y1·Y2 - a·X1·X2)
491 fn add_edwards(&self, other: &Self, a: FieldElement, d: FieldElement) -> Self {
492 // A = X1·X2, B = Y1·Y2, C = d·T1·T2, D = Z1·Z2
493 let a_val = self.x.mul(&other.x);
494 let b_val = self.y.mul(&other.y);
495 let c_val = d.mul(&self.t.mul(&other.t));
496 let d_val = self.z.mul(&other.z);
497
498 // E = (X1+Y1)·(X2+Y2) - A - B = X1·Y2 + Y1·X2
499 let e_val = self.x.add(&self.y).mul(&other.x.add(&other.y)).sub(&a_val).sub(&b_val);
500
501 // F = D - C, G = D + C, H = B - a·A
502 let f_val = d_val.sub(&c_val);
503 let g_val = d_val.add(&c_val);
504 let h_val = b_val.sub(&a.mul(&a_val));
505
506 // X3 = E·F, Y3 = G·H, Z3 = F·G, T3 = E·H
507 let x3 = e_val.mul(&f_val);
508 let y3 = g_val.mul(&h_val);
509 let z3 = f_val.mul(&g_val);
510 let t3 = e_val.mul(&h_val);
511
512 Self::new(x3, y3, z3, t3)
513 }
514
515 /// Double this extended point on an Edwards curve.
516 ///
517 /// Uses the extended Edwards doubling formulas which are optimized
518 /// for the case where both points are the same. This is more efficient
519 /// than the general addition formula.
520 ///
521 /// # Parameters
522 /// * `curve` - The curve parameters defining the doubling operation
523 ///
524 /// # Returns
525 /// The doubled point in extended coordinates
526 pub fn double(&self, curve: CurveType) -> Self {
527 match curve {
528 CurveType::Edwards { a, d } => self.double_edwards(a, d),
529 CurveType::Weierstrass { .. } => {
530 // For Weierstrass curves, convert to affine, double, then back to extended
531 let affine = self.to_affine();
532 let doubled_affine = point_add(&affine, &affine, curve);
533 Self::from_affine(doubled_affine.0, doubled_affine.1)
534 }
535 }
536 }
537
538 /// Double a point on an Edwards curve using extended coordinates.
539 ///
540 /// Uses the extended Edwards doubling formulas:
541 /// A = X², B = Y², C = 2·Z², D = a·A, E = (X+Y)² - A - B
542 /// F = C - D, G = C + D, H = B - D, I = E·F, J = E·H, K = G·H
543 /// X3 = I, Y3 = J, Z3 = K, T3 = I·J
544 ///
545 /// But we use the more efficient version that avoids recomputing squares.
546 fn double_edwards(&self, a: FieldElement, d: FieldElement) -> Self {
547 // A = X², B = Y², C = Z², D = T²
548 let a_val = self.x.square();
549 let b_val = self.y.square();
550 let c_val = self.z.square();
551 let d_val = self.t.square();
552
553 // E = (X+Y)² - A - B = 2·X·Y
554 let e_val = self.x.add(&self.y).square().sub(&a_val).sub(&b_val);
555
556 // F = C - d·D, G = C + d·D
557 let f_val = c_val.sub(&d.mul(&d_val));
558 let g_val = c_val.add(&d.mul(&d_val));
559
560 // H = B - a·A
561 let h_val = b_val.sub(&a.mul(&a_val));
562
563 // X3 = E·F, Y3 = G·H, Z3 = F·G, T3 = E·H
564 let x3 = e_val.mul(&f_val);
565 let y3 = g_val.mul(&h_val);
566 let z3 = f_val.mul(&g_val);
567 let t3 = e_val.mul(&h_val);
568
569 Self::new(x3, y3, z3, t3)
570 }
571
572 /// Compute scalar multiplication using the Montgomery ladder.
573 ///
574 /// This method performs constant-time scalar multiplication k * P using
575 /// the Montgomery ladder algorithm. The implementation uses extended
576 /// coordinates to maintain curve membership and avoid coordinate conversions.
577 ///
578 /// # Parameters
579 /// * `scalar` - The scalar multiplier (secret value in cryptographic use)
580 /// * `curve` - The curve parameters defining the group operation
581 ///
582 /// # Returns
583 /// The result k * P in extended coordinates
584 ///
585 /// # Security
586 /// This operation is constant-time and safe for cryptographic use with
587 /// secret scalars. The Montgomery ladder prevents timing attacks by
588 /// ensuring the same sequence of operations regardless of scalar bits.
589 pub fn scalar_mul(&self, scalar: &crate::BigInt, curve: CurveType) -> Self {
590 // Handle scalar = 0: return identity
591 if scalar.is_zero() {
592 return Self::identity();
593 }
594
595 // Handle scalar = 1: return the point itself
596 if *scalar == crate::BigInt::from_u64(1) {
597 return *self;
598 }
599
600 // Montgomery ladder algorithm
601 let mut r0 = Self::identity(); // Point at infinity
602 let mut r1 = *self; // Initial point
603
604 let scalar_bits = scalar.bit_length();
605
606 for i in (0..scalar_bits).rev() {
607 let bit = scalar.get_bit(i);
608
609 // Differential addition: r0, r1 = r0 + r1, 2*r0 (if bit=0) or 2*r1, r0 + r1 (if bit=1)
610 let (r0_new, r1_new) = if bit == 0 {
611 let sum = r0.add(&r1, curve);
612 let double_r0 = r0.double(curve);
613 (double_r0, sum)
614 } else {
615 let sum = r0.add(&r1, curve);
616 let double_r1 = r1.double(curve);
617 (sum, double_r1)
618 };
619
620 r0 = r0_new;
621 r1 = r1_new;
622 }
623
624 r0
625 }
626}
627
628/// Elliptic curve point addition using the curve's group law.
629///
630/// Computes the sum of two elliptic curve points according to the group operation
631/// defined by the curve equation. This is the fundamental operation for elliptic
632/// curve cryptography, used in ECDSA signatures, ECDH key exchange, and other protocols.
633///
634/// # Mathematical Definition
635///
636/// Point addition satisfies the elliptic curve group law:
637/// - **Commutativity**: P + Q = Q + P
638/// - **Associativity**: (P + Q) + R = P + (Q + R)
639/// - **Identity**: P + O = P (where O is point at infinity)
640/// - **Inverse**: P + (-P) = O
641///
642/// # Algorithm Details
643///
644/// ## Weierstrass Curves
645/// Uses chord-tangent formulas with case analysis:
646/// - **Different x-coordinates**: Standard addition formula
647/// - **Same x-coordinate**: Point doubling (if same y) or infinity (if different y)
648/// - **Point at infinity**: Identity element handling
649///
650/// ## Edwards Curves
651/// Uses unified addition formulas that work for all cases:
652/// - No special handling for doubling or infinity
653/// - Complete formulas prevent exceptional cases
654/// - Better performance and side-channel resistance
655///
656/// # Parameters
657/// * `p1` - First point on the elliptic curve
658/// * `p2` - Second point on the elliptic curve
659/// * `curve` - Curve type and parameters defining the group operation
660///
661/// # Returns
662/// The sum of the two points according to the curve's group law
663///
664/// # Security Considerations
665/// - Constant-time execution prevents timing attacks on point operations
666/// - No information leakage about point values through execution patterns
667/// - Safe for cryptographic use with secret curve points
668///
669/// # Examples
670/// ```ignore
671/// use clock_curve_math::field::elliptic_curve::*;
672///
673/// let curve = secp256k1_curve();
674/// let p1 = (FieldElement::from_u64(1), FieldElement::from_u64(2));
675/// let p2 = (FieldElement::from_u64(3), FieldElement::from_u64(4));
676///
677/// let sum = point_add(&p1, &p2, curve);
678/// assert!(is_on_curve(&sum, curve)); // Result is still on curve
679/// ```
680///
681/// # Point at Infinity
682/// Represented as (0,0) for both curve types. Addition with infinity:
683/// - P + (0,0) = P
684/// - (0,0) + (0,0) = (0,0)
685pub fn point_add(
686 p1: &(FieldElement, FieldElement),
687 p2: &(FieldElement, FieldElement),
688 curve: CurveType,
689) -> (FieldElement, FieldElement) {
690 match curve {
691 CurveType::Weierstrass { a, b: _ } => point_add_weierstrass(p1, p2, a),
692 CurveType::Edwards { a, d } => point_add_edwards(p1, p2, a, d),
693 }
694}
695
696/// Point addition for Weierstrass curves: y² = x³ + ax + b
697fn point_add_weierstrass(
698 p1: &(FieldElement, FieldElement),
699 p2: &(FieldElement, FieldElement),
700 a: FieldElement,
701) -> (FieldElement, FieldElement) {
702 let (x1, y1) = p1;
703 let (x2, y2) = p2;
704
705 // Point at infinity representations
706 let infinity = (FieldElement::from_u64(0), FieldElement::from_u64(0));
707
708 // Handle point at infinity
709 if *x1 == FieldElement::from_u64(0) && *y1 == FieldElement::from_u64(0) {
710 return *p2;
711 }
712 if *x2 == FieldElement::from_u64(0) && *y2 == FieldElement::from_u64(0) {
713 return *p1;
714 }
715
716 // Point addition formula for Weierstrass curves
717 if x1 == x2 {
718 if y1 == y2 {
719 // Point doubling
720 return point_double_weierstrass(p1, a);
721 } else {
722 // P + (-P) = infinity
723 return infinity;
724 }
725 }
726
727 // Standard point addition
728 let lambda = y2.sub(y1).mul(&x2.sub(x1).inv());
729 let x3 = lambda.mul(&lambda).sub(x1).sub(x2);
730 let y3 = lambda.mul(&x1.sub(&x3)).sub(y1);
731
732 (x3, y3)
733}
734
735/// Point doubling for Weierstrass curves
736fn point_double_weierstrass(p: &(FieldElement, FieldElement), a: FieldElement) -> (FieldElement, FieldElement) {
737 let (x, y) = p;
738
739 if *y == FieldElement::from_u64(0) {
740 // Point at infinity
741 return (FieldElement::from_u64(0), FieldElement::from_u64(0));
742 }
743
744 // Point doubling formula: λ = (3x² + a) / (2y)
745 let lambda = FieldElement::from_u64(3)
746 .mul(&x.mul(x))
747 .add(&a)
748 .mul(&FieldElement::from_u64(2).mul(y).inv());
749 let x3 = lambda.mul(&lambda).sub(&FieldElement::from_u64(2).mul(x));
750 let y3 = lambda.mul(&x.sub(&x3)).sub(y);
751
752 (x3, y3)
753}
754
755/// Point addition for Edwards curves: ax² + y² = 1 + dx²y²
756fn point_add_edwards(
757 p1: &(FieldElement, FieldElement),
758 p2: &(FieldElement, FieldElement),
759 a: FieldElement,
760 d: FieldElement,
761) -> (FieldElement, FieldElement) {
762 let (x1, y1) = p1;
763 let (x2, y2) = p2;
764
765 // Edwards curve addition formulas:
766 // x3 = (x1*y2 + y1*x2) / (1 + d*x1*x2*y1*y2)
767 // y3 = (y1*y2 - a*x1*x2) / (1 - d*x1*x2*y1*y2)
768
769 let x1y2 = x1.mul(y2);
770 let y1x2 = y1.mul(x2);
771 let x1x2 = x1.mul(x2);
772 let y1y2 = y1.mul(y2);
773 let x1x2y1y2 = x1x2.mul(&y1y2);
774
775 let denominator1 = FieldElement::from_u64(1).add(&d.mul(&x1x2y1y2));
776 let denominator2 = FieldElement::from_u64(1).sub(&d.mul(&x1x2y1y2));
777
778 let x3 = x1y2.add(&y1x2).mul(&denominator1.inv());
779 let y3 = y1y2.sub(&a.mul(&x1x2)).mul(&denominator2.inv());
780
781 (x3, y3)
782}
783
784/// Elliptic curve scalar multiplication using Montgomery ladder.
785///
786/// Computes `scalar * point` using the Montgomery ladder algorithm, which provides
787/// constant-time execution regardless of the scalar value. This is the core operation
788/// for elliptic curve cryptography, used in ECDSA signatures, ECDH key exchange, and
789/// other cryptographic protocols.
790///
791/// # Algorithm: Montgomery Ladder
792///
793/// The Montgomery ladder maintains two points (R0, R1) and performs:
794/// 1. Initialize: R0 = O (infinity), R1 = P
795/// 2. For each bit of scalar (MSB to LSB):
796/// - If bit = 0: R0, R1 = R0 + R1, 2*R0
797/// - If bit = 1: R0, R1 = 2*R1, R0 + R1
798/// 3. Result is R0
799///
800/// This algorithm ensures:
801/// - **Constant time**: Same operations regardless of scalar bits
802/// - **Regular execution**: No data-dependent control flow
803/// - **Side-channel resistance**: Prevents timing and cache attacks
804///
805/// # Security Critical
806///
807/// **High Security Risk**: Scalar multiplication handles secret values:
808/// - Private keys in ECDSA signatures
809/// - Ephemeral keys in ECDH exchange
810/// - Nonces and other cryptographic secrets
811///
812/// Any timing leak in this function can compromise cryptographic security.
813/// The Montgomery ladder prevents such leaks by constant-time execution.
814///
815/// # Parameters
816/// * `point` - Base point on the elliptic curve (should be on curve)
817/// * `scalar` - Scalar multiplier (secret value in cryptographic use)
818/// * `curve` - Curve parameters defining the group operation
819///
820/// # Returns
821/// The result of `scalar * point` according to the curve's group law
822///
823/// # Performance
824/// O(log scalar) point additions and doublings, constant-time.
825/// More expensive than simple point addition but essential for cryptography.
826///
827/// # Mathematical Properties
828/// - **Distributivity**: k*(P + Q) = k*P + k*Q
829/// - **Scalar addition**: (k + m)*P = k*P + m*P
830/// - **Identity**: 0*P = O (point at infinity)
831/// - **Generator**: If P is generator, k*P generates the subgroup
832///
833/// # Examples
834/// ```ignore
835/// use clock_curve_math::{BigInt, field::elliptic_curve::*};
836///
837/// let curve = secp256k1_curve();
838/// let generator = (gx, gy); // Generator point coordinates
839/// let private_key = BigInt::from_bytes(&private_key_bytes);
840///
841/// // Public key = private_key * generator
842/// let public_key = scalar_mul(&generator, &private_key, curve);
843///
844/// // ECDH shared secret = private_key * peer_public_key
845/// let shared_secret = scalar_mul(&peer_public_key, &private_key, curve);
846/// ```
847///
848/// # Implementation Notes
849/// - Assumes point is on curve (validation should be done by caller)
850/// - Handles scalar = 0 correctly (returns infinity)
851/// - No input validation for performance (cryptographic callers should validate)
852/// - Uses big-endian bit processing for consistency with BigInt representation
853pub fn scalar_mul(
854 point: &(FieldElement, FieldElement),
855 scalar: &crate::BigInt,
856 curve: CurveType,
857) -> (FieldElement, FieldElement) {
858 // Montgomery ladder algorithm for constant-time scalar multiplication
859 // Use correct identity element for each curve type
860 let r0 = match curve {
861 CurveType::Weierstrass { .. } => (FieldElement::from_u64(0), FieldElement::from_u64(0)), // Point at infinity
862 CurveType::Edwards { .. } => (FieldElement::from_u64(0), FieldElement::from_u64(1)), // Identity element
863 };
864 let mut r0 = r0;
865 let mut r1 = *point;
866
867 let scalar_bits = scalar.bit_length();
868
869 for i in (0..scalar_bits).rev() {
870 let bit = scalar.get_bit(i);
871
872 // Differential addition: r0, r1 = r0 + r1, 2*r0 (if bit=0) or 2*r1, r0 + r1 (if bit=1)
873 let (r0_new, r1_new) = if bit == 0 {
874 let sum = point_add(&r0, &r1, curve);
875 let double_r0 = point_add(&r0, &r0, curve);
876 (double_r0, sum)
877 } else {
878 let sum = point_add(&r0, &r1, curve);
879 let double_r1 = point_add(&r1, &r1, curve);
880 (sum, double_r1)
881 };
882
883 r0 = r0_new;
884 r1 = r1_new;
885 }
886
887 r0
888}
889
890/// Validates whether a point lies on the specified elliptic curve.
891///
892/// Verifies that the given point satisfies the curve equation for the specified
893/// curve type. Point validation is critical for cryptographic security to prevent
894/// attacks that rely on submitting invalid curve points.
895///
896/// # Validation Process
897///
898/// ## Point at Infinity
899/// Always considered valid (represented as (0,0) in both curve models)
900///
901/// ## Weierstrass Curves
902/// Checks: `y² ≡ x³ + ax + b mod p`
903/// - Computes both sides of the Weierstrass equation
904/// - Compares results for equality
905///
906/// ## Edwards Curves
907/// Checks: `ax² + y² ≡ 1 + dx²y² mod p`
908/// - Computes both sides of the Edwards equation
909/// - Verifies the twisted Edwards identity
910///
911/// # Security Importance
912///
913/// **Critical for Protocol Security**: Invalid point acceptance can lead to:
914/// - **Invalid curve attacks** on signature schemes
915/// - **Weak key generation** if points aren't validated
916/// - **Protocol failures** in key exchange schemes
917/// - **Side-channel leaks** from error handling paths
918///
919/// # Parameters
920/// * `point` - The point to validate (x, y coordinates)
921/// * `curve` - Curve parameters defining the equation to check
922///
923/// # Returns
924/// `true` if the point satisfies the curve equation, `false` otherwise
925///
926/// # Performance
927/// O(1) field multiplications and comparisons.
928/// Fast validation suitable for runtime use.
929///
930/// # Examples
931/// ```ignore
932/// use clock_curve_math::field::elliptic_curve::*;
933///
934/// let curve = secp256k1_curve();
935/// let valid_point = (FieldElement::from_u64(1), FieldElement::from_u64(2));
936/// let invalid_point = (FieldElement::from_u64(1), FieldElement::from_u64(999));
937///
938/// assert!(is_on_curve(&valid_point, curve)); // Assuming it's on curve
939/// assert!(!is_on_curve(&invalid_point, curve)); // Obviously not on curve
940///
941/// // Point at infinity always valid
942/// let infinity = (FieldElement::from_u64(0), FieldElement::from_u64(0));
943/// assert!(is_on_curve(&infinity, curve));
944/// ```
945///
946/// # Usage in Cryptography
947/// - **Public key validation**: Ensure received keys are valid curve points
948/// - **Signature verification**: Validate signature-related curve points
949/// - **Key exchange**: Verify peer public keys before computation
950/// - **Protocol safety**: Prevent invalid point attacks
951///
952/// # Implementation Notes
953/// - Assumes field elements are reduced modulo the field prime
954/// - No timing leaks in validation process
955/// - Point at infinity handling consistent across curve types
956pub fn is_on_curve(point: &(FieldElement, FieldElement), curve: CurveType) -> bool {
957 let (x, y) = point;
958
959 match curve {
960 CurveType::Weierstrass { a, b } => {
961 // For Weierstrass curves, (0,0) represents the point at infinity
962 if *x == FieldElement::from_u64(0) && *y == FieldElement::from_u64(0) {
963 return true;
964 }
965
966 // Check y² = x³ + ax + b
967 let left = y.mul(y);
968 let right = x.mul(x).mul(x).add(&a.mul(x)).add(&b);
969 left == right
970 }
971 CurveType::Edwards { a, d } => {
972 // For Edwards curves, check the curve equation: a*x² + y² = 1 + d*x²*y²
973 // Note: (0,0) is not necessarily on Edwards curves, unlike Weierstrass
974 let left = a.mul(&x.mul(x)).add(&y.mul(y));
975 let right = FieldElement::from_u64(1).add(&d.mul(&x.mul(x)).mul(&y.mul(y)));
976 left == right
977 }
978 }
979}
980
981/// Creates the Ed25519 elliptic curve parameters.
982///
983/// Returns a CurveType::Edwards configuration with the standard Ed25519 parameters
984/// as defined in RFC 8032. Ed25519 uses a twisted Edwards curve with equation:
985/// `-x² + y² = 1 - (121665/121666)·x²y²`
986///
987/// # Curve Parameters
988/// - **a**: -1 (coefficient of x² term)
989/// - **d**: -(121665/121666) mod p (cross term coefficient)
990/// - **p**: 2^255 - 19 (field prime)
991/// - **Order**: 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed (group order)
992///
993/// # Security Properties
994/// - **Twisted Edwards form**: Provides complete addition formulas
995/// - **Prime order subgroup**: Prevents small subgroup attacks
996/// - **Cofactor**: 8 (requires cofactor clearing in protocols)
997/// - **Field size**: 255 bits (conservative security level)
998///
999/// # Cryptographic Usage
1000/// - **Digital signatures**: Ed25519 signature scheme
1001/// - **Key exchange**: X25519 (Montgomery form of same curve)
1002/// - **Protocol**: RFC 8032 compliant implementation
1003///
1004/// # Performance
1005/// Optimized for the specific Ed25519 parameters with precomputed constants.
1006/// The d parameter is computed as -(121665 × 121666^(-1)) mod p.
1007///
1008/// # Examples
1009/// ```ignore
1010/// use clock_curve_math::field::elliptic_curve::*;
1011///
1012/// let curve = ed25519_curve();
1013/// match curve {
1014/// CurveType::Edwards { a, d } => {
1015/// // Verify standard parameters
1016/// assert_eq!(a, FieldElement::from_u64(0).sub(&FieldElement::from_u64(1)));
1017/// // d parameter computed correctly
1018/// }
1019/// _ => panic!("Expected Edwards curve"),
1020/// }
1021/// ```
1022pub fn ed25519_curve() -> CurveType {
1023 // Ed25519 parameters: a = -1, d = -121665/121666
1024 let a = FieldElement::from_u64(0).sub(&FieldElement::from_u64(1));
1025 // d = -121665 * (121666)^(-1) mod p
1026 let d_num = FieldElement::from_u64(121665);
1027 let d_den = FieldElement::from_u64(121666).inv();
1028 let d = FieldElement::from_u64(0).sub(&d_num.mul(&d_den));
1029
1030 CurveType::Edwards { a, d }
1031}
1032
1033/// Creates the secp256k1 elliptic curve parameters.
1034///
1035/// Returns a CurveType::Weierstrass configuration with the standard secp256k1
1036/// parameters as used in Bitcoin and other cryptocurrencies. The curve equation is:
1037/// `y² = x³ + 7` (simplified field representation)
1038///
1039/// # Curve Parameters
1040/// - **a**: 0 (no x term in the cubic)
1041/// - **b**: 7 (constant term)
1042/// - **p**: 2^256 - 2^32 - 977 (field prime)
1043/// - **Order**: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
1044/// - **Cofactor**: 1 (prime order group)
1045///
1046/// # Security Properties
1047/// - **Prime field**: No small characteristic vulnerabilities
1048/// - **Large prime order**: 256-bit security level
1049/// - **Well-studied**: Extensively analyzed since Bitcoin's creation
1050/// - **No known weaknesses**: Extensive cryptanalysis shows no practical attacks
1051///
1052/// # Cryptographic Usage
1053/// - **Digital signatures**: ECDSA in Bitcoin and other systems
1054/// - **Key exchange**: ECDH for secure communication
1055/// - **Blockchain**: Primary curve for cryptocurrency transactions
1056/// - **Standards**: Widely adopted in financial and blockchain applications
1057///
1058/// # Performance
1059/// Optimized for the secp256k1 parameters (a=0 simplifies some formulas).
1060/// The simplified Weierstrass form allows for efficient point operations.
1061///
1062/// # Historical Context
1063/// secp256k1 was selected for Bitcoin due to:
1064/// - **Security**: 128-bit security level against known attacks
1065/// - **Performance**: Efficient on constrained devices
1066/// - **Adoption**: Became the de facto standard for cryptocurrencies
1067/// - **Analysis**: Years of cryptanalysis confirm security
1068///
1069/// # Examples
1070/// ```ignore
1071/// use clock_curve_math::field::elliptic_curve::*;
1072///
1073/// let curve = secp256k1_curve();
1074/// match curve {
1075/// CurveType::Weierstrass { a, b } => {
1076/// // Verify standard parameters
1077/// assert_eq!(a, FieldElement::from_u64(0));
1078/// assert_eq!(b, FieldElement::from_u64(7));
1079/// }
1080/// _ => panic!("Expected Weierstrass curve"),
1081/// }
1082///
1083/// // Use for Bitcoin-style ECDSA
1084/// let generator = (gx, gy); // Standard generator point
1085/// let private_key = BigInt::from_bytes(&private_key_bytes);
1086/// let public_key = scalar_mul(&generator, &private_key, curve);
1087/// ```
1088pub fn secp256k1_curve() -> CurveType {
1089 // secp256k1: y² = x³ + 7
1090 let a = FieldElement::from_u64(0);
1091 let b = FieldElement::from_u64(7);
1092
1093 CurveType::Weierstrass { a, b }
1094}
1095
1096#[cfg(all(test, feature = "alloc"))]
1097include!("elliptic_curve/tests.rs");