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, 1); // selects a
38//! let selected = FieldElement::conditional_select(&a, &b, 0); // 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    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.cmp(&p) != core::cmp::Ordering::Less {
103            return Err(crate::error::MathError::InvalidBytes);
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    /// Constant-time conditional selection.
174    ///
175    /// Returns `a` if `flag == 1`, `b` if `flag == 0`.
176    /// Executes in constant time regardless of the flag value.
177    ///
178    /// # Safety
179    ///
180    /// `flag` should be either `0` or `1` for correct behavior.
181    ///
182    /// # Examples
183    ///
184    /// ```
185    /// use clock_curve_math::FieldElement;
186    ///
187    /// let a = FieldElement::from_u64(10);
188    /// let b = FieldElement::from_u64(20);
189    ///
190    /// let selected = FieldElement::conditional_select(&a, &b, 1); // selects a
191    /// assert_eq!(selected, a);
192    ///
193    /// let selected = FieldElement::conditional_select(&a, &b, 0); // selects b
194    /// assert_eq!(selected, b);
195    /// ```
196    pub fn conditional_select(a: &Self, b: &Self, flag: u64) -> Self {
197        let a_limbs = a.inner.limbs();
198        let b_limbs = b.inner.limbs();
199        let result_limbs = ct::ct_select_array(&a_limbs, &b_limbs, flag);
200        Self {
201            inner: BigInt::from_limbs(&result_limbs),
202        }
203    }
204
205    /// Constant-time conditional swap.
206    ///
207    /// Swaps `a` and `b` if `flag == 1`, leaves them unchanged if `flag == 0`.
208    /// Executes in constant time regardless of the flag value.
209    ///
210    /// # Safety
211    ///
212    /// `flag` should be either `0` or `1` for correct behavior.
213    ///
214    /// # Examples
215    ///
216    /// ```
217    /// use clock_curve_math::FieldElement;
218    ///
219    /// let mut a = FieldElement::from_u64(10);
220    /// let mut b = FieldElement::from_u64(20);
221    ///
222    /// FieldElement::conditional_swap(&mut a, &mut b, 0);
223    /// assert_eq!(a, FieldElement::from_u64(10)); // unchanged
224    /// assert_eq!(b, FieldElement::from_u64(20)); // unchanged
225    ///
226    /// FieldElement::conditional_swap(&mut a, &mut b, 1);
227    /// assert_eq!(a, FieldElement::from_u64(20)); // swapped
228    /// assert_eq!(b, FieldElement::from_u64(10)); // swapped
229    /// ```
230    pub fn conditional_swap(a: &mut Self, b: &mut Self, flag: u64) {
231        let mut a_limbs = a.inner.limbs();
232        let mut b_limbs = b.inner.limbs();
233        ct::ct_swap(&mut a_limbs, &mut b_limbs, flag);
234        a.inner = BigInt::from_limbs(&a_limbs);
235        b.inner = BigInt::from_limbs(&b_limbs);
236    }
237
238    /// Check if the value is valid (in range [0, p)).
239    ///
240    /// Returns true if the field element represents a value in [0, p).
241    /// Field elements created through the public API are always valid.
242    ///
243    /// # Examples
244    ///
245    /// ```
246    /// use clock_curve_math::FieldElement;
247    ///
248    /// let element = FieldElement::from_u64(42);
249    /// assert!(element.is_valid());
250    /// ```
251    pub fn is_valid(&self) -> bool {
252        crate::field::helpers::is_valid_field(self)
253    }
254
255    /// Compute the additive inverse (negation).
256    ///
257    /// Returns `-self mod p`, which satisfies `self + (-self) ≡ 0 mod p`.
258    ///
259    /// # Examples
260    ///
261    /// ```
262    /// use clock_curve_math::{FieldElement, FieldOps};
263    ///
264    /// let a = FieldElement::from_u64(5);
265    /// let neg_a = a.neg();
266    /// let sum = a.add(&neg_a);
267    /// assert_eq!(sum, FieldElement::from_u64(0));
268    /// ```
269    pub fn neg(&self) -> Self {
270        let zero = Self::from_u64(0);
271        zero.sub(self)
272    }
273
274    /// Get the inner BigInt value (in Montgomery form).
275    ///
276    /// This is primarily used by internal helper functions.
277    pub(crate) fn inner(&self) -> &BigInt {
278        &self.inner
279    }
280
281    /// Generate a random field element.
282    ///
283    /// Uses the provided random number generator to create a uniformly random
284    /// field element in the range [0, p).
285    ///
286    /// # Examples
287    ///
288    /// ```rust
289    /// # #[cfg(feature = "rand")]
290    /// use clock_curve_math::FieldElement;
291    /// # #[cfg(feature = "rand")]
292    /// use clock_rand::Rng;
293    ///
294    /// # #[cfg(feature = "rand")]
295    /// # fn example() {
296    /// let mut rng = clock_rand::Xoshiro256Plus::new(42);
297    /// let random_element = FieldElement::random(&mut rng);
298    /// # }
299    /// ```
300    ///
301    /// # Security Notes
302    ///
303    /// Uses rejection sampling to ensure the generated value is always in the valid range [0, p).
304    /// This may require multiple random draws in the worst case, but the probability of rejection
305    /// is very low since p ≈ 2^255.
306    #[cfg(feature = "rand")]
307    pub fn random<R: clock_rand::Rng>(rng: &mut R) -> Self {
308        loop {
309            // Generate 32 random bytes
310            let mut bytes = [0u8; 32];
311            rng.fill_bytes(&mut bytes);
312
313            // Try to create field element from bytes
314            // Since p is very close to 2^255, most random 32-byte values will be >= p
315            // We use rejection sampling to ensure we get a valid value
316            if let Ok(element) = Self::from_bytes(&bytes) {
317                return element;
318            }
319            // If from_bytes fails (value >= p), try again
320        }
321    }
322
323    /// Generate a random non-zero field element.
324    ///
325    /// Uses the provided random number generator to create a uniformly random
326    /// field element in the range [1, p).
327    ///
328    /// # Examples
329    ///
330    /// ```rust
331    /// # #[cfg(feature = "rand")]
332    /// use clock_curve_math::FieldElement;
333    /// # #[cfg(feature = "rand")]
334    /// use clock_rand::Xoshiro256Plus;
335    ///
336    /// # #[cfg(feature = "rand")]
337    /// # fn example() {
338    /// let mut rng = clock_rand::Xoshiro256Plus::new(42);
339    /// let random_element = FieldElement::random_nonzero(&mut rng);
340    /// assert_ne!(random_element, FieldElement::from_u64(0));
341    /// # }
342    /// ```
343    #[cfg(feature = "rand")]
344    pub fn random_nonzero<R: clock_rand::Rng>(rng: &mut R) -> Self {
345        loop {
346            let element = Self::random(rng);
347            if !element.is_zero() {
348                return element;
349            }
350        }
351    }
352
353    /// Check if this field element is zero.
354    pub fn is_zero(&self) -> bool {
355        // Convert from Montgomery form and check if zero
356        let value = crate::montgomery::from_montgomery_p(&self.inner);
357        value.is_zero()
358    }
359}
360
361/// Trait for field element operations.
362///
363/// This trait defines the arithmetic operations available on field elements.
364/// All operations are constant-time and automatically reduce their results
365/// modulo the field prime p = 2^255 - 19.
366pub trait FieldOps {
367    /// Modular addition.
368    ///
369    /// Computes `(self + rhs) mod p` in constant time.
370    ///
371    /// # Examples
372    ///
373    /// ```
374    /// use clock_curve_math::{FieldElement, FieldOps};
375    ///
376    /// let a = FieldElement::from_u64(10);
377    /// let b = FieldElement::from_u64(20);
378    /// let sum = a.add(&b);
379    /// assert_eq!(sum, FieldElement::from_u64(30));
380    /// ```
381    fn add(&self, rhs: &Self) -> Self;
382
383    /// Modular subtraction.
384    ///
385    /// Computes `(self - rhs) mod p` in constant time.
386    ///
387    /// # Examples
388    ///
389    /// ```
390    /// use clock_curve_math::{FieldElement, FieldOps};
391    ///
392    /// let a = FieldElement::from_u64(20);
393    /// let b = FieldElement::from_u64(10);
394    /// let diff = a.sub(&b);
395    /// assert_eq!(diff, FieldElement::from_u64(10));
396    /// ```
397    fn sub(&self, rhs: &Self) -> Self;
398
399    /// Montgomery multiplication.
400    ///
401    /// Computes `(self * rhs) mod p` using Montgomery arithmetic for efficiency.
402    ///
403    /// # Examples
404    ///
405    /// ```
406    /// use clock_curve_math::{FieldElement, FieldOps};
407    ///
408    /// let a = FieldElement::from_u64(10);
409    /// let b = FieldElement::from_u64(20);
410    /// let product = a.mul(&b);
411    /// assert_eq!(product, FieldElement::from_u64(200));
412    /// ```
413    fn mul(&self, rhs: &Self) -> Self;
414
415    /// Squaring (optimized).
416    ///
417    /// Computes `(self * self) mod p`. This is typically faster than general multiplication.
418    ///
419    /// # Examples
420    ///
421    /// ```
422    /// use clock_curve_math::{FieldElement, FieldOps};
423    ///
424    /// let a = FieldElement::from_u64(10);
425    /// let square = a.square();
426    /// assert_eq!(square, FieldElement::from_u64(100));
427    /// ```
428    fn square(&self) -> Self;
429
430    /// Constant-time modular inverse.
431    ///
432    /// Computes the modular inverse of `self` modulo p using Fermat's Little Theorem.
433    /// The result satisfies `(self * inv) ≡ 1 mod p`.
434    ///
435    /// # Panics
436    ///
437    /// Panics if `self` is zero (which has no multiplicative inverse).
438    ///
439    /// # Examples
440    ///
441    /// ```
442    /// use clock_curve_math::{FieldElement, FieldOps};
443    ///
444    /// let a = FieldElement::from_u64(5);
445    /// let inv = a.inv();
446    /// let product = a.mul(&inv);
447    /// assert_eq!(product, FieldElement::from_u64(1));
448    /// ```
449    fn inv(&self) -> Self;
450
451    /// Modular exponentiation.
452    ///
453    /// Computes `(self ^ exp) mod p` using constant-time exponentiation by squaring.
454    ///
455    /// # Examples
456    ///
457    /// ```
458    /// use clock_curve_math::{FieldElement, BigInt, FieldOps};
459    ///
460    /// let base = FieldElement::from_u64(2);
461    /// let exp = BigInt::from_u64(10);
462    /// let result = base.pow(&exp);
463    /// assert_eq!(result, FieldElement::from_u64(1024)); // 2^10 = 1024
464    /// ```
465    fn pow(&self, exp: &BigInt) -> Self;
466
467    /// Modular exponentiation with input validation.
468    ///
469    /// Computes `(self ^ exp) mod p` using constant-time exponentiation by squaring.
470    /// Validates that the exponent is non-negative.
471    ///
472    /// # Examples
473    ///
474    /// ```
475    /// use clock_curve_math::{FieldElement, BigInt, FieldOps};
476    ///
477    /// let base = FieldElement::from_u64(2);
478    /// let exp = BigInt::from_u64(10);
479    /// let result = base.pow_checked(&exp).unwrap();
480    /// assert_eq!(result, FieldElement::from_u64(1024)); // 2^10 = 1024
481    /// ```
482    ///
483    /// # Errors
484    ///
485    /// Returns [`crate::error::MathError::InvalidExponent`] if the exponent is negative.
486    fn pow_checked(&self, exp: &BigInt) -> Result<Self, crate::error::MathError>
487    where
488        Self: Sized;
489}
490
491impl FieldOps for FieldElement {
492    fn add(&self, rhs: &Self) -> Self {
493        let p = BigInt::from_limbs(&P_LIMBS);
494        let sum = self.inner.add(&rhs.inner);
495
496        // Constant-time reduction: subtract p, then add it back if the result would be negative
497        let diff = sum.sub(&p);
498        let sign_bit = (diff.limbs()[3] >> 63) & 1;
499        let needs_carry = sign_bit; // Add p back if result would be negative
500
501        let mask = ct::ct_mask(needs_carry);
502        let p_masked = BigInt::from_limbs(&[
503            P_LIMBS[0] & mask,
504            P_LIMBS[1] & mask,
505            P_LIMBS[2] & mask,
506            P_LIMBS[3] & mask,
507        ]);
508        let result = diff.add(&p_masked);
509
510        Self { inner: result }
511    }
512
513    fn sub(&self, rhs: &Self) -> Self {
514        let _p = BigInt::from_limbs(&P_LIMBS);
515        let diff = self.inner.sub(&rhs.inner);
516
517        // Constant-time correction: add p if diff is negative (underflow)
518        let is_negative = ct::ct_is_zero(diff.limbs()[3] >> 63) ^ 1; // 1 if MSB is set (negative)
519
520        let mask = ct::ct_mask(is_negative);
521        let p_masked = BigInt::from_limbs(&[
522            P_LIMBS[0] & mask,
523            P_LIMBS[1] & mask,
524            P_LIMBS[2] & mask,
525            P_LIMBS[3] & mask,
526        ]);
527        let result = diff.add(&p_masked);
528
529        Self { inner: result }
530    }
531
532    fn mul(&self, rhs: &Self) -> Self {
533        let p = BigInt::from_limbs(&P_LIMBS);
534        let n_prime = BigInt::from_limbs(&N_PRIME_P);
535        let result = montgomery_mul(&self.inner, &rhs.inner, &p, &n_prime);
536        Self { inner: result }
537    }
538
539    fn square(&self) -> Self {
540        // For now, use the same multiplication. In the future, we could optimize
541        // Montgomery squaring specifically, but the current montgomery_mul
542        // is already quite efficient.
543        self.mul(self)
544    }
545
546    fn inv(&self) -> Self {
547        Self {
548            inner: crate::field::helpers::field_inv(self),
549        }
550    }
551
552    fn pow(&self, exp: &BigInt) -> Self {
553        Self {
554            inner: crate::field::helpers::field_pow(self, exp),
555        }
556    }
557
558    fn pow_checked(&self, exp: &BigInt) -> Result<Self, crate::error::MathError> {
559        crate::validation::validate_exponent(exp)?;
560        Ok(Self {
561            inner: crate::field::helpers::field_pow(self, exp),
562        })
563    }
564}
565
566impl Default for FieldElement {
567    fn default() -> Self {
568        Self::from_u64(0)
569    }
570}