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        // Correct Ed25519 extended coordinates addition formula
493        // A = (Y1 - X1) * (Y2 - X2)
494        let a_val = self.y.sub(&self.x).mul(&other.y.sub(&other.x));
495
496        // B = (Y1 + X1) * (Y2 + X2)
497        let b_val = self.y.add(&self.x).mul(&other.y.add(&other.x));
498
499        // C = 2 * d * T1 * T2
500        let c_val = d.mul(&self.t.mul(&other.t)).mul(&FieldElement::from_u64(2));
501
502        // D = 2 * Z1 * Z2
503        let d_val = self.z.mul(&other.z).mul(&FieldElement::from_u64(2));
504
505        // E = B - A
506        let e_val = b_val.sub(&a_val);
507
508        // F = D - C
509        let f_val = d_val.sub(&c_val);
510
511        // G = D + C
512        let g_val = d_val.add(&c_val);
513
514        // H = B + A
515        let h_val = b_val.add(&a_val);
516
517        // X3 = E * F
518        let x3 = e_val.mul(&f_val);
519
520        // Y3 = G * H
521        let y3 = g_val.mul(&h_val);
522
523        // Z3 = F * G
524        let z3 = f_val.mul(&g_val);
525
526        // T3 = E * H
527        let t3 = e_val.mul(&h_val);
528
529        Self::new(x3, y3, z3, t3)
530    }
531
532    /// Double this extended point on an Edwards curve.
533    ///
534    /// Uses the extended Edwards doubling formulas which are optimized
535    /// for the case where both points are the same. This is more efficient
536    /// than the general addition formula.
537    ///
538    /// # Parameters
539    /// * `curve` - The curve parameters defining the doubling operation
540    ///
541    /// # Returns
542    /// The doubled point in extended coordinates
543    pub fn double(&self, curve: CurveType) -> Self {
544        match curve {
545            CurveType::Edwards { a, d } => self.double_edwards(a, d),
546            CurveType::Weierstrass { .. } => {
547                // For Weierstrass curves, convert to affine, double, then back to extended
548                let affine = self.to_affine();
549                let doubled_affine = point_add(&affine, &affine, curve);
550                Self::from_affine(doubled_affine.0, doubled_affine.1)
551            }
552        }
553    }
554
555    /// Double a point on an Edwards curve using extended coordinates.
556    ///
557    /// Uses the extended Edwards doubling formulas:
558    /// A = X², B = Y², C = 2·Z², D = a·A, E = (X+Y)² - A - B
559    /// F = C - D, G = C + D, H = B - D, I = E·F, J = E·H, K = G·H
560    /// X3 = I, Y3 = J, Z3 = K, T3 = I·J
561    ///
562    /// But we use the more efficient version that avoids recomputing squares.
563    fn double_edwards(&self, a: FieldElement, d: FieldElement) -> Self {
564        // A = X², B = Y², C = Z², D = T²
565        let a_val = self.x.square();
566        let b_val = self.y.square();
567        let c_val = self.z.square();
568        let d_val = self.t.square();
569
570        // E = (X+Y)² - A - B = 2·X·Y
571        let e_val = self.x.add(&self.y).square().sub(&a_val).sub(&b_val);
572
573        // F = C - d·D, G = C + d·D
574        let f_val = c_val.sub(&d.mul(&d_val));
575        let g_val = c_val.add(&d.mul(&d_val));
576
577        // H = B - a·A
578        let h_val = b_val.sub(&a.mul(&a_val));
579
580        // X3 = E·F, Y3 = G·H, Z3 = F·G, T3 = E·H
581        let x3 = e_val.mul(&f_val);
582        let y3 = g_val.mul(&h_val);
583        let z3 = f_val.mul(&g_val);
584        let t3 = e_val.mul(&h_val);
585
586        Self::new(x3, y3, z3, t3)
587    }
588
589    /// Compute scalar multiplication using the Montgomery ladder.
590    ///
591    /// This method performs constant-time scalar multiplication k * P using
592    /// the Montgomery ladder algorithm. The implementation uses extended
593    /// coordinates to maintain curve membership and avoid coordinate conversions.
594    ///
595    /// # Parameters
596    /// * `scalar` - The scalar multiplier (secret value in cryptographic use)
597    /// * `curve` - The curve parameters defining the group operation
598    ///
599    /// # Returns
600    /// The result k * P in extended coordinates
601    ///
602    /// # Security
603    /// This operation is constant-time and safe for cryptographic use with
604    /// secret scalars. The Montgomery ladder prevents timing attacks by
605    /// ensuring the same sequence of operations regardless of scalar bits.
606    pub fn scalar_mul(&self, scalar: &crate::BigInt, curve: CurveType) -> Self {
607        // Handle scalar = 0: return identity
608        if scalar.is_zero() {
609            return Self::identity();
610        }
611
612        // Handle scalar = 1: return the point itself
613        if *scalar == crate::BigInt::from_u64(1) {
614            return *self;
615        }
616
617        // Montgomery ladder algorithm
618        let mut r0 = Self::identity(); // Point at infinity
619        let mut r1 = *self; // Initial point
620
621        let scalar_bits = scalar.bit_length();
622
623        for i in (0..scalar_bits).rev() {
624            let bit = scalar.get_bit(i);
625
626            // Differential addition: r0, r1 = r0 + r1, 2*r0 (if bit=0) or 2*r1, r0 + r1 (if bit=1)
627            let (r0_new, r1_new) = if bit == 0 {
628                let sum = r0.add(&r1, curve);
629                let double_r0 = r0.double(curve);
630                (double_r0, sum)
631            } else {
632                let sum = r0.add(&r1, curve);
633                let double_r1 = r1.double(curve);
634                (sum, double_r1)
635            };
636
637            r0 = r0_new;
638            r1 = r1_new;
639        }
640
641        r0
642    }
643}
644
645/// Elliptic curve point addition using the curve's group law.
646///
647/// Computes the sum of two elliptic curve points according to the group operation
648/// defined by the curve equation. This is the fundamental operation for elliptic
649/// curve cryptography, used in ECDSA signatures, ECDH key exchange, and other protocols.
650///
651/// # Mathematical Definition
652///
653/// Point addition satisfies the elliptic curve group law:
654/// - **Commutativity**: P + Q = Q + P
655/// - **Associativity**: (P + Q) + R = P + (Q + R)
656/// - **Identity**: P + O = P (where O is point at infinity)
657/// - **Inverse**: P + (-P) = O
658///
659/// # Algorithm Details
660///
661/// ## Weierstrass Curves
662/// Uses chord-tangent formulas with case analysis:
663/// - **Different x-coordinates**: Standard addition formula
664/// - **Same x-coordinate**: Point doubling (if same y) or infinity (if different y)
665/// - **Point at infinity**: Identity element handling
666///
667/// ## Edwards Curves
668/// Uses unified addition formulas that work for all cases:
669/// - No special handling for doubling or infinity
670/// - Complete formulas prevent exceptional cases
671/// - Better performance and side-channel resistance
672///
673/// # Parameters
674/// * `p1` - First point on the elliptic curve
675/// * `p2` - Second point on the elliptic curve
676/// * `curve` - Curve type and parameters defining the group operation
677///
678/// # Returns
679/// The sum of the two points according to the curve's group law
680///
681/// # Security Considerations
682/// - Constant-time execution prevents timing attacks on point operations
683/// - No information leakage about point values through execution patterns
684/// - Safe for cryptographic use with secret curve points
685///
686/// # Examples
687/// ```ignore
688/// use clock_curve_math::field::elliptic_curve::*;
689///
690/// let curve = secp256k1_curve();
691/// let p1 = (FieldElement::from_u64(1), FieldElement::from_u64(2));
692/// let p2 = (FieldElement::from_u64(3), FieldElement::from_u64(4));
693///
694/// let sum = point_add(&p1, &p2, curve);
695/// assert!(is_on_curve(&sum, curve)); // Result is still on curve
696/// ```
697///
698/// # Point at Infinity
699/// Represented as (0,0) for both curve types. Addition with infinity:
700/// - P + (0,0) = P
701/// - (0,0) + (0,0) = (0,0)
702pub fn point_add(
703    p1: &(FieldElement, FieldElement),
704    p2: &(FieldElement, FieldElement),
705    curve: CurveType,
706) -> (FieldElement, FieldElement) {
707    match curve {
708        CurveType::Weierstrass { a, b: _ } => point_add_weierstrass(p1, p2, a),
709        CurveType::Edwards { a, d } => point_add_edwards(p1, p2, a, d),
710    }
711}
712
713/// Point addition for Weierstrass curves: y² = x³ + ax + b
714fn point_add_weierstrass(
715    p1: &(FieldElement, FieldElement),
716    p2: &(FieldElement, FieldElement),
717    a: FieldElement,
718) -> (FieldElement, FieldElement) {
719    let (x1, y1) = p1;
720    let (x2, y2) = p2;
721
722    // Point at infinity representations
723    let infinity = (FieldElement::from_u64(0), FieldElement::from_u64(0));
724
725    // Handle point at infinity
726    if *x1 == FieldElement::from_u64(0) && *y1 == FieldElement::from_u64(0) {
727        return *p2;
728    }
729    if *x2 == FieldElement::from_u64(0) && *y2 == FieldElement::from_u64(0) {
730        return *p1;
731    }
732
733    // Point addition formula for Weierstrass curves
734    if x1 == x2 {
735        if y1 == y2 {
736            // Point doubling
737            return point_double_weierstrass(p1, a);
738        } else {
739            // P + (-P) = infinity
740            return infinity;
741        }
742    }
743
744    // Standard point addition
745    let lambda = y2.sub(y1).mul(&x2.sub(x1).inv());
746    let x3 = lambda.mul(&lambda).sub(x1).sub(x2);
747    let y3 = lambda.mul(&x1.sub(&x3)).sub(y1);
748
749    (x3, y3)
750}
751
752/// Point doubling for Weierstrass curves
753fn point_double_weierstrass(p: &(FieldElement, FieldElement), a: FieldElement) -> (FieldElement, FieldElement) {
754    let (x, y) = p;
755
756    if *y == FieldElement::from_u64(0) {
757        // Point at infinity
758        return (FieldElement::from_u64(0), FieldElement::from_u64(0));
759    }
760
761    // Point doubling formula: λ = (3x² + a) / (2y)
762    let lambda = FieldElement::from_u64(3)
763        .mul(&x.mul(x))
764        .add(&a)
765        .mul(&FieldElement::from_u64(2).mul(y).inv());
766    let x3 = lambda.mul(&lambda).sub(&FieldElement::from_u64(2).mul(x));
767    let y3 = lambda.mul(&x.sub(&x3)).sub(y);
768
769    (x3, y3)
770}
771
772/// Point addition for Edwards curves: ax² + y² = 1 + dx²y²
773fn point_add_edwards(
774    p1: &(FieldElement, FieldElement),
775    p2: &(FieldElement, FieldElement),
776    a: FieldElement,
777    d: FieldElement,
778) -> (FieldElement, FieldElement) {
779    let (x1, y1) = p1;
780    let (x2, y2) = p2;
781
782    // Edwards curve addition formulas:
783    // x3 = (x1*y2 + y1*x2) / (1 + d*x1*x2*y1*y2)
784    // y3 = (y1*y2 - a*x1*x2) / (1 - d*x1*x2*y1*y2)
785
786    let x1y2 = x1.mul(y2);
787    let y1x2 = y1.mul(x2);
788    let x1x2 = x1.mul(x2);
789    let y1y2 = y1.mul(y2);
790    let x1x2y1y2 = x1x2.mul(&y1y2);
791
792    let denominator1 = FieldElement::from_u64(1).add(&d.mul(&x1x2y1y2));
793    let denominator2 = FieldElement::from_u64(1).sub(&d.mul(&x1x2y1y2));
794
795    let x3 = x1y2.add(&y1x2).mul(&denominator1.inv());
796    let y3 = y1y2.sub(&a.mul(&x1x2)).mul(&denominator2.inv());
797
798    (x3, y3)
799}
800
801/// Elliptic curve scalar multiplication using Montgomery ladder.
802///
803/// Computes `scalar * point` using the Montgomery ladder algorithm, which provides
804/// constant-time execution regardless of the scalar value. This is the core operation
805/// for elliptic curve cryptography, used in ECDSA signatures, ECDH key exchange, and
806/// other cryptographic protocols.
807///
808/// # Algorithm: Montgomery Ladder
809///
810/// The Montgomery ladder maintains two points (R0, R1) and performs:
811/// 1. Initialize: R0 = O (infinity), R1 = P
812/// 2. For each bit of scalar (MSB to LSB):
813///    - If bit = 0: R0, R1 = R0 + R1, 2*R0
814///    - If bit = 1: R0, R1 = 2*R1, R0 + R1
815/// 3. Result is R0
816///
817/// This algorithm ensures:
818/// - **Constant time**: Same operations regardless of scalar bits
819/// - **Regular execution**: No data-dependent control flow
820/// - **Side-channel resistance**: Prevents timing and cache attacks
821///
822/// # Security Critical
823///
824/// **High Security Risk**: Scalar multiplication handles secret values:
825/// - Private keys in ECDSA signatures
826/// - Ephemeral keys in ECDH exchange
827/// - Nonces and other cryptographic secrets
828///
829/// Any timing leak in this function can compromise cryptographic security.
830/// The Montgomery ladder prevents such leaks by constant-time execution.
831///
832/// # Parameters
833/// * `point` - Base point on the elliptic curve (should be on curve)
834/// * `scalar` - Scalar multiplier (secret value in cryptographic use)
835/// * `curve` - Curve parameters defining the group operation
836///
837/// # Returns
838/// The result of `scalar * point` according to the curve's group law
839///
840/// # Performance
841/// O(log scalar) point additions and doublings, constant-time.
842/// More expensive than simple point addition but essential for cryptography.
843///
844/// # Mathematical Properties
845/// - **Distributivity**: k*(P + Q) = k*P + k*Q
846/// - **Scalar addition**: (k + m)*P = k*P + m*P
847/// - **Identity**: 0*P = O (point at infinity)
848/// - **Generator**: If P is generator, k*P generates the subgroup
849///
850/// # Examples
851/// ```ignore
852/// use clock_curve_math::{BigInt, field::elliptic_curve::*};
853///
854/// let curve = secp256k1_curve();
855/// let generator = (gx, gy); // Generator point coordinates
856/// let private_key = BigInt::from_bytes(&private_key_bytes);
857///
858/// // Public key = private_key * generator
859/// let public_key = scalar_mul(&generator, &private_key, curve);
860///
861/// // ECDH shared secret = private_key * peer_public_key
862/// let shared_secret = scalar_mul(&peer_public_key, &private_key, curve);
863/// ```
864///
865/// # Implementation Notes
866/// - Assumes point is on curve (validation should be done by caller)
867/// - Handles scalar = 0 correctly (returns infinity)
868/// - No input validation for performance (cryptographic callers should validate)
869/// - Uses big-endian bit processing for consistency with BigInt representation
870pub fn scalar_mul(
871    point: &(FieldElement, FieldElement),
872    scalar: &crate::BigInt,
873    curve: CurveType,
874) -> (FieldElement, FieldElement) {
875    // Montgomery ladder algorithm for constant-time scalar multiplication
876    // Use correct identity element for each curve type
877    let r0 = match curve {
878        CurveType::Weierstrass { .. } => (FieldElement::from_u64(0), FieldElement::from_u64(0)), // Point at infinity
879        CurveType::Edwards { .. } => (FieldElement::from_u64(0), FieldElement::from_u64(1)), // Identity element
880    };
881    let mut r0 = r0;
882    let mut r1 = *point;
883
884    let scalar_bits = scalar.bit_length();
885
886    for i in (0..scalar_bits).rev() {
887        let bit = scalar.get_bit(i);
888
889        // Differential addition: r0, r1 = r0 + r1, 2*r0 (if bit=0) or 2*r1, r0 + r1 (if bit=1)
890        let (r0_new, r1_new) = if bit == 0 {
891            let sum = point_add(&r0, &r1, curve);
892            let double_r0 = point_add(&r0, &r0, curve);
893            (double_r0, sum)
894        } else {
895            let sum = point_add(&r0, &r1, curve);
896            let double_r1 = point_add(&r1, &r1, curve);
897            (sum, double_r1)
898        };
899
900        r0 = r0_new;
901        r1 = r1_new;
902    }
903
904    r0
905}
906
907/// Validates whether a point lies on the specified elliptic curve.
908///
909/// Verifies that the given point satisfies the curve equation for the specified
910/// curve type. Point validation is critical for cryptographic security to prevent
911/// attacks that rely on submitting invalid curve points.
912///
913/// # Validation Process
914///
915/// ## Point at Infinity
916/// Always considered valid (represented as (0,0) in both curve models)
917///
918/// ## Weierstrass Curves
919/// Checks: `y² ≡ x³ + ax + b mod p`
920/// - Computes both sides of the Weierstrass equation
921/// - Compares results for equality
922///
923/// ## Edwards Curves
924/// Checks: `ax² + y² ≡ 1 + dx²y² mod p`
925/// - Computes both sides of the Edwards equation
926/// - Verifies the twisted Edwards identity
927///
928/// # Security Importance
929///
930/// **Critical for Protocol Security**: Invalid point acceptance can lead to:
931/// - **Invalid curve attacks** on signature schemes
932/// - **Weak key generation** if points aren't validated
933/// - **Protocol failures** in key exchange schemes
934/// - **Side-channel leaks** from error handling paths
935///
936/// # Parameters
937/// * `point` - The point to validate (x, y coordinates)
938/// * `curve` - Curve parameters defining the equation to check
939///
940/// # Returns
941/// `true` if the point satisfies the curve equation, `false` otherwise
942///
943/// # Performance
944/// O(1) field multiplications and comparisons.
945/// Fast validation suitable for runtime use.
946///
947/// # Examples
948/// ```ignore
949/// use clock_curve_math::field::elliptic_curve::*;
950///
951/// let curve = secp256k1_curve();
952/// let valid_point = (FieldElement::from_u64(1), FieldElement::from_u64(2));
953/// let invalid_point = (FieldElement::from_u64(1), FieldElement::from_u64(999));
954///
955/// assert!(is_on_curve(&valid_point, curve));    // Assuming it's on curve
956/// assert!(!is_on_curve(&invalid_point, curve)); // Obviously not on curve
957///
958/// // Point at infinity always valid
959/// let infinity = (FieldElement::from_u64(0), FieldElement::from_u64(0));
960/// assert!(is_on_curve(&infinity, curve));
961/// ```
962///
963/// # Usage in Cryptography
964/// - **Public key validation**: Ensure received keys are valid curve points
965/// - **Signature verification**: Validate signature-related curve points
966/// - **Key exchange**: Verify peer public keys before computation
967/// - **Protocol safety**: Prevent invalid point attacks
968///
969/// # Implementation Notes
970/// - Assumes field elements are reduced modulo the field prime
971/// - No timing leaks in validation process
972/// - Point at infinity handling consistent across curve types
973pub fn is_on_curve(point: &(FieldElement, FieldElement), curve: CurveType) -> bool {
974    let (x, y) = point;
975
976    match curve {
977        CurveType::Weierstrass { a, b } => {
978            // For Weierstrass curves, (0,0) represents the point at infinity
979            if *x == FieldElement::from_u64(0) && *y == FieldElement::from_u64(0) {
980                return true;
981            }
982
983            // Check y² = x³ + ax + b
984            let left = y.mul(y);
985            let right = x.mul(x).mul(x).add(&a.mul(x)).add(&b);
986            left == right
987        }
988        CurveType::Edwards { a, d } => {
989            // For Edwards curves, check the curve equation: a*x² + y² = 1 + d*x²*y²
990            // Note: (0,0) is not necessarily on Edwards curves, unlike Weierstrass
991            let left = a.mul(&x.mul(x)).add(&y.mul(y));
992            let right = FieldElement::from_u64(1).add(&d.mul(&x.mul(x)).mul(&y.mul(y)));
993            left == right
994        }
995    }
996}
997
998/// Creates the Ed25519 elliptic curve parameters.
999///
1000/// Returns a CurveType::Edwards configuration with the standard Ed25519 parameters
1001/// as defined in RFC 8032. Ed25519 uses a twisted Edwards curve with equation:
1002/// `-x² + y² = 1 - (121665/121666)·x²y²`
1003///
1004/// # Curve Parameters
1005/// - **a**: -1 (coefficient of x² term)
1006/// - **d**: -(121665/121666) mod p (cross term coefficient)
1007/// - **p**: 2^255 - 19 (field prime)
1008/// - **Order**: 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed (group order)
1009///
1010/// # Security Properties
1011/// - **Twisted Edwards form**: Provides complete addition formulas
1012/// - **Prime order subgroup**: Prevents small subgroup attacks
1013/// - **Cofactor**: 8 (requires cofactor clearing in protocols)
1014/// - **Field size**: 255 bits (conservative security level)
1015///
1016/// # Cryptographic Usage
1017/// - **Digital signatures**: Ed25519 signature scheme
1018/// - **Key exchange**: X25519 (Montgomery form of same curve)
1019/// - **Protocol**: RFC 8032 compliant implementation
1020///
1021/// # Performance
1022/// Optimized for the specific Ed25519 parameters with precomputed constants.
1023/// The d parameter is computed as -(121665 × 121666^(-1)) mod p.
1024///
1025/// # Examples
1026/// ```ignore
1027/// use clock_curve_math::field::elliptic_curve::*;
1028///
1029/// let curve = ed25519_curve();
1030/// match curve {
1031///     CurveType::Edwards { a, d } => {
1032///         // Verify standard parameters
1033///         assert_eq!(a, FieldElement::from_u64(0).sub(&FieldElement::from_u64(1)));
1034///         // d parameter computed correctly
1035///     }
1036///     _ => panic!("Expected Edwards curve"),
1037/// }
1038/// ```
1039pub fn ed25519_curve() -> CurveType {
1040    // Ed25519 parameters: a = -1, d = -121665/121666
1041    let a = FieldElement::from_u64(0).sub(&FieldElement::from_u64(1));
1042    // d = -121665 * (121666)^(-1) mod p
1043    let d_num = FieldElement::from_u64(121665);
1044    let d_den = FieldElement::from_u64(121666).inv();
1045    let d = FieldElement::from_u64(0).sub(&d_num.mul(&d_den));
1046
1047    CurveType::Edwards { a, d }
1048}
1049
1050/// Creates the secp256k1 elliptic curve parameters.
1051///
1052/// Returns a CurveType::Weierstrass configuration with the standard secp256k1
1053/// parameters as used in Bitcoin and other cryptocurrencies. The curve equation is:
1054/// `y² = x³ + 7` (simplified field representation)
1055///
1056/// # Curve Parameters
1057/// - **a**: 0 (no x term in the cubic)
1058/// - **b**: 7 (constant term)
1059/// - **p**: 2^256 - 2^32 - 977 (field prime)
1060/// - **Order**: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
1061/// - **Cofactor**: 1 (prime order group)
1062///
1063/// # Security Properties
1064/// - **Prime field**: No small characteristic vulnerabilities
1065/// - **Large prime order**: 256-bit security level
1066/// - **Well-studied**: Extensively analyzed since Bitcoin's creation
1067/// - **No known weaknesses**: Extensive cryptanalysis shows no practical attacks
1068///
1069/// # Cryptographic Usage
1070/// - **Digital signatures**: ECDSA in Bitcoin and other systems
1071/// - **Key exchange**: ECDH for secure communication
1072/// - **Blockchain**: Primary curve for cryptocurrency transactions
1073/// - **Standards**: Widely adopted in financial and blockchain applications
1074///
1075/// # Performance
1076/// Optimized for the secp256k1 parameters (a=0 simplifies some formulas).
1077/// The simplified Weierstrass form allows for efficient point operations.
1078///
1079/// # Historical Context
1080/// secp256k1 was selected for Bitcoin due to:
1081/// - **Security**: 128-bit security level against known attacks
1082/// - **Performance**: Efficient on constrained devices
1083/// - **Adoption**: Became the de facto standard for cryptocurrencies
1084/// - **Analysis**: Years of cryptanalysis confirm security
1085///
1086/// # Examples
1087/// ```ignore
1088/// use clock_curve_math::field::elliptic_curve::*;
1089///
1090/// let curve = secp256k1_curve();
1091/// match curve {
1092///     CurveType::Weierstrass { a, b } => {
1093///         // Verify standard parameters
1094///         assert_eq!(a, FieldElement::from_u64(0));
1095///         assert_eq!(b, FieldElement::from_u64(7));
1096///     }
1097///     _ => panic!("Expected Weierstrass curve"),
1098/// }
1099///
1100/// // Use for Bitcoin-style ECDSA
1101/// let generator = (gx, gy); // Standard generator point
1102/// let private_key = BigInt::from_bytes(&private_key_bytes);
1103/// let public_key = scalar_mul(&generator, &private_key, curve);
1104/// ```
1105pub fn secp256k1_curve() -> CurveType {
1106    // secp256k1: y² = x³ + 7
1107    let a = FieldElement::from_u64(0);
1108    let b = FieldElement::from_u64(7);
1109
1110    CurveType::Weierstrass { a, b }
1111}
1112
1113#[cfg(all(test, feature = "alloc"))]
1114include!("elliptic_curve/tests.rs");