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");