clock_curve_math/field/
field_element.rs

1//! FieldElement implementation.
2//!
3//! This module provides arithmetic operations in the finite field modulo p = 2^255 - 19,
4//! which is the prime field used by the Curve25519 elliptic curve.
5//!
6//! # Field Parameters
7//!
8//! - **Prime modulus (p)**: 2^255 - 19
9//! - **Field size**: ~2^255 elements
10//! - **Representation**: Montgomery form for efficient multiplication
11//!
12//! # Security Properties
13//!
14//! All operations are designed to be constant-time to prevent timing-based
15//! side-channel attacks. This includes arithmetic operations, comparisons,
16//! and conditional operations.
17//!
18//! # Examples
19//!
20//! ```
21//! use clock_curve_math::{FieldElement, FieldOps};
22//!
23//! // Create field elements
24//! let a = FieldElement::from_u64(10);
25//! let b = FieldElement::from_u64(20);
26//!
27//! // Perform arithmetic
28//! let sum = a.add(&b);
29//! let product = a.mul(&b);
30//! let square = a.square();
31//!
32//! // Modular inverse
33//! let inv_a = a.inv();
34//! assert_eq!(a.mul(&inv_a), FieldElement::from_u64(1));
35//!
36//! // Conditional operations (constant-time)
37//! let selected = FieldElement::conditional_select(&a, &b, clock_curve_math::ct::Choice::from_bool(true)); // selects a
38//! let selected = FieldElement::conditional_select(&a, &b, clock_curve_math::ct::Choice::from_bool(false)); // selects b
39//! ```
40
41use crate::bigint::BigInt;
42use crate::constants::P_LIMBS;
43use crate::ct;
44use crate::montgomery::{N_PRIME_P, montgomery_mul};
45
46/// FieldElement represents an element of the field modulo p = 2^255 - 19.
47///
48/// Values are stored in Montgomery form for efficient multiplication.
49#[derive(Clone, Copy, Debug, PartialEq, Eq)]
50pub struct FieldElement {
51    /// The value in Montgomery form
52    pub(crate) inner: BigInt,
53}
54
55#[cfg(feature = "serde")]
56impl serde::Serialize for FieldElement {
57    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58    where
59        S: serde::Serializer,
60    {
61        // Serialize as bytes for canonical representation
62        self.to_bytes().serialize(serializer)
63    }
64}
65
66#[cfg(feature = "serde")]
67impl<'de> serde::Deserialize<'de> for FieldElement {
68    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69    where
70        D: serde::Deserializer<'de>,
71    {
72        // Deserialize from bytes
73        let bytes = <[u8; 32]>::deserialize(deserializer)?;
74        Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
75    }
76}
77
78impl FieldElement {
79    /// Create a FieldElement from bytes (canonical representation).
80    ///
81    /// The bytes must represent a value in the range [0, p). Values outside this
82    /// range will result in an error.
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// use clock_curve_math::FieldElement;
88    ///
89    /// let bytes = [1u8; 32]; // Little-endian representation of a small number
90    /// let element = FieldElement::from_bytes(&bytes).unwrap();
91    /// assert_eq!(element.to_bytes(), bytes);
92    /// ```
93    ///
94    /// # Errors
95    ///
96    /// Returns [`crate::error::MathError::InvalidBytes`] if the byte representation is not in [0, p).
97    pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, crate::error::MathError> {
98        let value = BigInt::from_bytes(bytes);
99
100        // Check if value < p
101        let p = BigInt::from_limbs(&P_LIMBS);
102        if value.ct_cmp(&p) != core::cmp::Ordering::Less {
103            return Err(crate::error::MathError::InvalidFieldElement);
104        }
105
106        // Convert to Montgomery form
107        let mont_value = crate::montgomery::to_montgomery_p(&value);
108
109        Ok(Self { inner: mont_value })
110    }
111
112    /// Convert to bytes (canonical representation).
113    ///
114    /// Returns the canonical little-endian byte representation of the field element.
115    /// The result is guaranteed to be in the range [0, p).
116    ///
117    /// # Examples
118    ///
119    /// ```
120    /// use clock_curve_math::FieldElement;
121    ///
122    /// let element = FieldElement::from_u64(42);
123    /// let bytes = element.to_bytes();
124    /// let reconstructed = FieldElement::from_bytes(&bytes).unwrap();
125    /// assert_eq!(element, reconstructed);
126    /// ```
127    pub fn to_bytes(&self) -> [u8; 32] {
128        let value = crate::montgomery::from_montgomery_p(&self.inner);
129        value.to_bytes()
130    }
131
132    /// Create a FieldElement from a u64 value.
133    ///
134    /// The value is automatically reduced modulo p if necessary.
135    ///
136    /// # Examples
137    ///
138    /// ```
139    /// use clock_curve_math::FieldElement;
140    ///
141    /// let zero = FieldElement::from_u64(0);
142    /// let one = FieldElement::from_u64(1);
143    /// let large = FieldElement::from_u64(u64::MAX); // Will be reduced mod p
144    /// ```
145    pub fn from_u64(value: u64) -> Self {
146        let bigint = BigInt::from_u64(value);
147        let mont_value = crate::montgomery::to_montgomery_p(&bigint);
148        Self { inner: mont_value }
149    }
150
151    /// Create a FieldElement from a BigInt value with validation.
152    ///
153    /// The value must be in the range [0, p) where p is the field modulus.
154    ///
155    /// # Examples
156    ///
157    /// ```
158    /// use clock_curve_math::{FieldElement, BigInt};
159    ///
160    /// let value = BigInt::from_u64(42);
161    /// let element = FieldElement::from_bigint(&value).unwrap();
162    /// ```
163    ///
164    /// # Errors
165    ///
166    /// Returns [`crate::error::MathError::InvalidFieldElement`] if the value is not in [0, p).
167    pub fn from_bigint(value: &BigInt) -> Result<Self, crate::error::MathError> {
168        crate::validation::validate_field_bigint(value)?;
169        let mont_value = crate::montgomery::to_montgomery_p(value);
170        Ok(Self { inner: mont_value })
171    }
172
173    /// Convert a FieldElement to a BigInt.
174    ///
175    /// Returns the Montgomery representation of the field element as a BigInt.
176    /// To get the regular representation, use `from_montgomery` on the result.
177    ///
178    /// # Examples
179    ///
180    /// ```ignore
181    /// use clock_curve_math::{FieldElement, BigInt};
182    ///
183    /// let element = FieldElement::from_u64(42);
184    /// let bigint = element.to_bigint();
185    /// let regular = clock_curve_math::montgomery::from_montgomery_p(&bigint);
186    /// assert_eq!(regular, BigInt::from_u64(42));
187    /// ```
188    pub fn to_bigint(&self) -> BigInt {
189        self.inner
190    }
191
192    /// Constant-time conditional selection.
193    ///
194    /// Returns `a` if `flag == 1`, `b` if `flag == 0`.
195    /// Executes in constant time regardless of the flag value.
196    ///
197    /// # Safety
198    ///
199    /// `flag` should be either `0` or `1` for correct behavior.
200    ///
201    /// # Examples
202    ///
203    /// ```
204    /// use clock_curve_math::FieldElement;
205    ///
206    /// let a = FieldElement::from_u64(10);
207    /// let b = FieldElement::from_u64(20);
208    ///
209    /// let selected = FieldElement::conditional_select(&a, &b, clock_curve_math::ct::Choice::from_bool(true)); // selects a
210    /// assert_eq!(selected, a);
211    ///
212    /// let selected = FieldElement::conditional_select(&a, &b, clock_curve_math::ct::Choice::from_bool(false)); // selects b
213    /// assert_eq!(selected, b);
214    /// ```
215    pub fn conditional_select(a: &Self, b: &Self, choice: crate::ct::Choice) -> Self {
216        let a_limbs = a.inner.limbs();
217        let b_limbs = b.inner.limbs();
218        let result_limbs = ct::ct_select_array(&a_limbs, &b_limbs, choice.0);
219        Self {
220            inner: BigInt::from_limbs(&result_limbs),
221        }
222    }
223
224    /// Constant-time conditional swap.
225    ///
226    /// Swaps `a` and `b` if `flag == 1`, leaves them unchanged if `flag == 0`.
227    /// Executes in constant time regardless of the flag value.
228    ///
229    /// # Safety
230    ///
231    /// `flag` should be either `0` or `1` for correct behavior.
232    ///
233    /// # Examples
234    ///
235    /// ```
236    /// use clock_curve_math::FieldElement;
237    ///
238    /// let mut a = FieldElement::from_u64(10);
239    /// let mut b = FieldElement::from_u64(20);
240    ///
241    /// FieldElement::conditional_swap(&mut a, &mut b, 0);
242    /// assert_eq!(a, FieldElement::from_u64(10)); // unchanged
243    /// assert_eq!(b, FieldElement::from_u64(20)); // unchanged
244    ///
245    /// FieldElement::conditional_swap(&mut a, &mut b, 1);
246    /// assert_eq!(a, FieldElement::from_u64(20)); // swapped
247    /// assert_eq!(b, FieldElement::from_u64(10)); // swapped
248    /// ```
249    pub fn conditional_swap(a: &mut Self, b: &mut Self, flag: u64) {
250        let mut a_limbs = a.inner.limbs();
251        let mut b_limbs = b.inner.limbs();
252        ct::ct_swap(&mut a_limbs, &mut b_limbs, flag);
253        a.inner = BigInt::from_limbs(&a_limbs);
254        b.inner = BigInt::from_limbs(&b_limbs);
255    }
256
257    /// Check if the value is valid (in range [0, p)).
258    ///
259    /// Returns true if the field element represents a value in [0, p).
260    /// Field elements created through the public API are always valid.
261    ///
262    /// # Examples
263    ///
264    /// ```
265    /// use clock_curve_math::FieldElement;
266    ///
267    /// let element = FieldElement::from_u64(42);
268    /// assert!(element.is_valid());
269    /// ```
270    pub fn is_valid(&self) -> bool {
271        crate::field::helpers::is_valid_field(self)
272    }
273
274    /// Compute the additive inverse (negation).
275    ///
276    /// Returns `-self mod p`, which satisfies `self + (-self) ≡ 0 mod p`.
277    ///
278    /// # Examples
279    ///
280    /// ```
281    /// use clock_curve_math::{FieldElement, FieldOps};
282    ///
283    /// let a = FieldElement::from_u64(5);
284    /// let neg_a = a.neg();
285    /// let sum = a.add(&neg_a);
286    /// assert_eq!(sum, FieldElement::from_u64(0));
287    /// ```
288    pub fn neg(&self) -> Self {
289        let zero = Self::from_u64(0);
290        zero.sub(self)
291    }
292
293    /// Get the inner BigInt value (in Montgomery form).
294    ///
295    /// This is primarily used by internal helper functions.
296    pub(crate) fn inner(&self) -> &BigInt {
297        &self.inner
298    }
299
300    /// Generate a random field element.
301    ///
302    /// Uses the provided random number generator to create a uniformly random
303    /// field element in the range [0, p).
304    ///
305    /// # Examples
306    ///
307    /// ```rust
308    /// # #[cfg(feature = "rand")]
309    /// use clock_curve_math::FieldElement;
310    /// # #[cfg(feature = "rand")]
311    /// use clock_rand::Rng;
312    ///
313    /// # #[cfg(feature = "rand")]
314    /// # fn example() {
315    /// let mut rng = clock_rand::Xoshiro256Plus::new(42);
316    /// let random_element = FieldElement::random(&mut rng);
317    /// # }
318    /// ```
319    ///
320    /// # Security Notes
321    ///
322    /// Uses rejection sampling to ensure the generated value is always in the valid range [0, p).
323    /// This may require multiple random draws in the worst case, but the probability of rejection
324    /// is very low since p ≈ 2^255.
325    #[cfg(feature = "rand")]
326    pub fn random<R: clock_rand::Rng>(rng: &mut R) -> Self {
327        loop {
328            // Generate 32 random bytes
329            let mut bytes = [0u8; 32];
330            rng.fill_bytes(&mut bytes);
331
332            // Try to create field element from bytes
333            // Since p is very close to 2^255, most random 32-byte values will be >= p
334            // We use rejection sampling to ensure we get a valid value
335            if let Ok(element) = Self::from_bytes(&bytes) {
336                return element;
337            }
338            // If from_bytes fails (value >= p), try again
339        }
340    }
341
342    /// Generate a random non-zero field element.
343    ///
344    /// Uses the provided random number generator to create a uniformly random
345    /// field element in the range [1, p).
346    ///
347    /// # Examples
348    ///
349    /// ```rust
350    /// # #[cfg(feature = "rand")]
351    /// use clock_curve_math::FieldElement;
352    /// # #[cfg(feature = "rand")]
353    /// use clock_rand::Xoshiro256Plus;
354    ///
355    /// # #[cfg(feature = "rand")]
356    /// # fn example() {
357    /// let mut rng = clock_rand::Xoshiro256Plus::new(42);
358    /// let random_element = FieldElement::random_nonzero(&mut rng);
359    /// assert_ne!(random_element, FieldElement::from_u64(0));
360    /// # }
361    /// ```
362    #[cfg(feature = "rand")]
363    pub fn random_nonzero<R: clock_rand::Rng>(rng: &mut R) -> Self {
364        loop {
365            let element = Self::random(rng);
366            if !element.is_zero() {
367                return element;
368            }
369        }
370    }
371
372    /// Check if this field element is zero.
373    ///
374    /// Returns `true` if the field element represents the additive identity (zero).
375    ///
376    /// # Examples
377    ///
378    /// ```
379    /// use clock_curve_math::FieldElement;
380    ///
381    /// let zero = FieldElement::from_u64(0);
382    /// let nonzero = FieldElement::from_u64(42);
383    ///
384    /// assert!(zero.is_zero());
385    /// assert!(!nonzero.is_zero());
386    /// ```
387    pub fn is_zero(&self) -> bool {
388        // Convert from Montgomery form and check if zero
389        let value = crate::montgomery::from_montgomery_p(&self.inner);
390        value.is_zero()
391    }
392}
393
394/// Trait for field element operations.
395///
396/// This trait defines the arithmetic operations available on field elements.
397/// All operations are constant-time and automatically reduce their results
398/// modulo the field prime p = 2^255 - 19.
399pub trait FieldOps {
400    /// Modular addition.
401    ///
402    /// Computes `(self + rhs) mod p` in constant time.
403    ///
404    /// # Examples
405    ///
406    /// ```
407    /// use clock_curve_math::{FieldElement, FieldOps};
408    ///
409    /// let a = FieldElement::from_u64(10);
410    /// let b = FieldElement::from_u64(20);
411    /// let sum = a.add(&b);
412    /// assert_eq!(sum, FieldElement::from_u64(30));
413    /// ```
414    fn add(&self, rhs: &Self) -> Self;
415
416    /// Modular subtraction.
417    ///
418    /// Computes `(self - rhs) mod p` in constant time.
419    ///
420    /// # Examples
421    ///
422    /// ```
423    /// use clock_curve_math::{FieldElement, FieldOps};
424    ///
425    /// let a = FieldElement::from_u64(20);
426    /// let b = FieldElement::from_u64(10);
427    /// let diff = a.sub(&b);
428    /// assert_eq!(diff, FieldElement::from_u64(10));
429    /// ```
430    fn sub(&self, rhs: &Self) -> Self;
431
432    /// Montgomery multiplication.
433    ///
434    /// Computes `(self * rhs) mod p` using Montgomery arithmetic for efficiency.
435    ///
436    /// # Examples
437    ///
438    /// ```
439    /// use clock_curve_math::{FieldElement, FieldOps};
440    ///
441    /// let a = FieldElement::from_u64(10);
442    /// let b = FieldElement::from_u64(20);
443    /// let product = a.mul(&b);
444    /// assert_eq!(product, FieldElement::from_u64(200));
445    /// ```
446    fn mul(&self, rhs: &Self) -> Self;
447
448    /// Squaring (optimized).
449    ///
450    /// Computes `(self * self) mod p`. This is typically faster than general multiplication.
451    ///
452    /// # Examples
453    ///
454    /// ```
455    /// use clock_curve_math::{FieldElement, FieldOps};
456    ///
457    /// let a = FieldElement::from_u64(10);
458    /// let square = a.square();
459    /// assert_eq!(square, FieldElement::from_u64(100));
460    /// ```
461    fn square(&self) -> Self;
462
463    /// Constant-time modular inverse.
464    ///
465    /// Computes the modular inverse of `self` modulo p using Fermat's Little Theorem.
466    /// The result satisfies `(self * inv) ≡ 1 mod p`.
467    ///
468    /// # Panics
469    ///
470    /// Panics if `self` is zero (which has no multiplicative inverse).
471    ///
472    /// # Examples
473    ///
474    /// ```
475    /// use clock_curve_math::{FieldElement, FieldOps};
476    ///
477    /// let a = FieldElement::from_u64(5);
478    /// let inv = a.inv();
479    /// let product = a.mul(&inv);
480    /// assert_eq!(product, FieldElement::from_u64(1));
481    /// ```
482    fn inv(&self) -> Self;
483
484    /// Modular exponentiation.
485    ///
486    /// Computes `(self ^ exp) mod p` using constant-time exponentiation by squaring.
487    ///
488    /// # Examples
489    ///
490    /// ```
491    /// use clock_curve_math::{FieldElement, BigInt, FieldOps};
492    ///
493    /// let base = FieldElement::from_u64(2);
494    /// let exp = BigInt::from_u64(10);
495    /// let result = base.pow(&exp);
496    /// assert_eq!(result, FieldElement::from_u64(1024)); // 2^10 = 1024
497    /// ```
498    fn pow(&self, exp: &BigInt) -> Self;
499
500    /// Modular exponentiation with input validation.
501    ///
502    /// Computes `(self ^ exp) mod p` using constant-time exponentiation by squaring.
503    /// Validates that the exponent is non-negative.
504    ///
505    /// # Examples
506    ///
507    /// ```
508    /// use clock_curve_math::{FieldElement, BigInt, FieldOps};
509    ///
510    /// let base = FieldElement::from_u64(2);
511    /// let exp = BigInt::from_u64(10);
512    /// let result = base.pow_checked(&exp).unwrap();
513    /// assert_eq!(result, FieldElement::from_u64(1024)); // 2^10 = 1024
514    /// ```
515    ///
516    /// # Errors
517    ///
518    /// Returns [`crate::error::MathError::InvalidExponent`] if the exponent is negative.
519    fn pow_checked(&self, exp: &BigInt) -> Result<Self, crate::error::MathError>
520    where
521        Self: Sized;
522}
523
524impl FieldOps for FieldElement {
525    fn add(&self, rhs: &Self) -> Self {
526        let p = BigInt::from_limbs(&P_LIMBS);
527        let sum = self.inner.add(&rhs.inner);
528
529        // Constant-time reduction: subtract p, then add it back if the result would be negative
530        let diff = sum.sub(&p);
531        let sign_bit = (diff.limbs()[3] >> 63) & 1;
532        let needs_carry = sign_bit; // Add p back if result would be negative
533
534        let mask = ct::ct_mask(needs_carry);
535        let p_masked = BigInt::from_limbs(&[
536            P_LIMBS[0] & mask,
537            P_LIMBS[1] & mask,
538            P_LIMBS[2] & mask,
539            P_LIMBS[3] & mask,
540        ]);
541        let result = diff.add(&p_masked);
542
543        Self { inner: result }
544    }
545
546    fn sub(&self, rhs: &Self) -> Self {
547        let _p = BigInt::from_limbs(&P_LIMBS);
548        let diff = self.inner.sub(&rhs.inner);
549
550        // Constant-time correction: add p if diff is negative (underflow)
551        let is_negative = ct::ct_is_zero(diff.limbs()[3] >> 63) ^ 1; // 1 if MSB is set (negative)
552
553        let mask = ct::ct_mask(is_negative);
554        let p_masked = BigInt::from_limbs(&[
555            P_LIMBS[0] & mask,
556            P_LIMBS[1] & mask,
557            P_LIMBS[2] & mask,
558            P_LIMBS[3] & mask,
559        ]);
560        let result = diff.add(&p_masked);
561
562        Self { inner: result }
563    }
564
565    fn mul(&self, rhs: &Self) -> Self {
566        let p = BigInt::from_limbs(&P_LIMBS);
567        let n_prime = BigInt::from_limbs(&N_PRIME_P);
568        let result = montgomery_mul(&self.inner, &rhs.inner, &p, &n_prime);
569        Self { inner: result }
570    }
571
572    fn square(&self) -> Self {
573        let p = BigInt::from_limbs(&P_LIMBS);
574        let n_prime = BigInt::from_limbs(&N_PRIME_P);
575        let result = crate::montgomery::montgomery_square(&self.inner, &p, &n_prime);
576        Self { inner: result }
577    }
578
579    fn inv(&self) -> Self {
580        Self {
581            inner: crate::field::helpers::field_inv(self),
582        }
583    }
584
585    fn pow(&self, exp: &BigInt) -> Self {
586        Self {
587            inner: crate::field::helpers::field_pow(self, exp),
588        }
589    }
590
591    fn pow_checked(&self, exp: &BigInt) -> Result<Self, crate::error::MathError> {
592        crate::validation::validate_exponent(exp)?;
593        Ok(Self {
594            inner: crate::field::helpers::field_pow(self, exp),
595        })
596    }
597}
598
599impl Default for FieldElement {
600    fn default() -> Self {
601        Self::from_u64(0)
602    }
603}