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