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;
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
55impl FieldElement {
56    /// Create a FieldElement from bytes (canonical representation).
57    ///
58    /// The bytes must represent a value in the range [0, p). Values outside this
59    /// range will result in an error.
60    ///
61    /// # Examples
62    ///
63    /// ```
64    /// use clock_curve_math::FieldElement;
65    ///
66    /// let bytes = [1u8; 32]; // Little-endian representation of a small number
67    /// let element = FieldElement::from_bytes(&bytes).unwrap();
68    /// assert_eq!(element.to_bytes(), bytes);
69    /// ```
70    ///
71    /// # Errors
72    ///
73    /// Returns [`crate::error::MathError::InvalidBytes`] if the byte representation is not in [0, p).
74    pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, crate::error::MathError> {
75        let value = BigInt::from_bytes(bytes);
76
77        // Check if value < p
78        let p = BigInt::from_limbs(&P_LIMBS);
79        if value.cmp(&p) != core::cmp::Ordering::Less {
80            return Err(crate::error::MathError::InvalidBytes);
81        }
82
83        // Convert to Montgomery form
84        let mont_value = crate::montgomery::to_montgomery_p(&value);
85
86        Ok(Self { inner: mont_value })
87    }
88
89    /// Convert to bytes (canonical representation).
90    ///
91    /// Returns the canonical little-endian byte representation of the field element.
92    /// The result is guaranteed to be in the range [0, p).
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use clock_curve_math::FieldElement;
98    ///
99    /// let element = FieldElement::from_u64(42);
100    /// let bytes = element.to_bytes();
101    /// let reconstructed = FieldElement::from_bytes(&bytes).unwrap();
102    /// assert_eq!(element, reconstructed);
103    /// ```
104    pub fn to_bytes(&self) -> [u8; 32] {
105        let value = crate::montgomery::from_montgomery_p(&self.inner);
106        value.to_bytes()
107    }
108
109    /// Create a FieldElement from a u64 value.
110    ///
111    /// The value is automatically reduced modulo p if necessary.
112    ///
113    /// # Examples
114    ///
115    /// ```
116    /// use clock_curve_math::FieldElement;
117    ///
118    /// let zero = FieldElement::from_u64(0);
119    /// let one = FieldElement::from_u64(1);
120    /// let large = FieldElement::from_u64(u64::MAX); // Will be reduced mod p
121    /// ```
122    pub fn from_u64(value: u64) -> Self {
123        let bigint = BigInt::from_u64(value);
124        let mont_value = crate::montgomery::to_montgomery_p(&bigint);
125        Self { inner: mont_value }
126    }
127
128    /// Create a FieldElement from a BigInt value with validation.
129    ///
130    /// The value must be in the range [0, p) where p is the field modulus.
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// use clock_curve_math::{FieldElement, BigInt};
136    ///
137    /// let value = BigInt::from_u64(42);
138    /// let element = FieldElement::from_bigint(&value).unwrap();
139    /// ```
140    ///
141    /// # Errors
142    ///
143    /// Returns [`crate::error::MathError::InvalidFieldElement`] if the value is not in [0, p).
144    pub fn from_bigint(value: &BigInt) -> Result<Self, crate::error::MathError> {
145        crate::validation::validate_field_bigint(value)?;
146        let mont_value = crate::montgomery::to_montgomery_p(value);
147        Ok(Self { inner: mont_value })
148    }
149
150    /// Constant-time conditional selection.
151    ///
152    /// Returns `a` if `flag == 1`, `b` if `flag == 0`.
153    /// Executes in constant time regardless of the flag value.
154    ///
155    /// # Safety
156    ///
157    /// `flag` should be either `0` or `1` for correct behavior.
158    ///
159    /// # Examples
160    ///
161    /// ```
162    /// use clock_curve_math::FieldElement;
163    ///
164    /// let a = FieldElement::from_u64(10);
165    /// let b = FieldElement::from_u64(20);
166    ///
167    /// let selected = FieldElement::conditional_select(&a, &b, 1); // selects a
168    /// assert_eq!(selected, a);
169    ///
170    /// let selected = FieldElement::conditional_select(&a, &b, 0); // selects b
171    /// assert_eq!(selected, b);
172    /// ```
173    pub fn conditional_select(a: &Self, b: &Self, flag: u64) -> Self {
174        let a_limbs = a.inner.limbs();
175        let b_limbs = b.inner.limbs();
176        let result_limbs = ct::ct_select_array(&a_limbs, &b_limbs, flag);
177        Self {
178            inner: BigInt::from_limbs(&result_limbs),
179        }
180    }
181
182    /// Constant-time conditional swap.
183    ///
184    /// Swaps `a` and `b` if `flag == 1`, leaves them unchanged if `flag == 0`.
185    /// Executes in constant time regardless of the flag value.
186    ///
187    /// # Safety
188    ///
189    /// `flag` should be either `0` or `1` for correct behavior.
190    ///
191    /// # Examples
192    ///
193    /// ```
194    /// use clock_curve_math::FieldElement;
195    ///
196    /// let mut a = FieldElement::from_u64(10);
197    /// let mut b = FieldElement::from_u64(20);
198    ///
199    /// FieldElement::conditional_swap(&mut a, &mut b, 0);
200    /// assert_eq!(a, FieldElement::from_u64(10)); // unchanged
201    /// assert_eq!(b, FieldElement::from_u64(20)); // unchanged
202    ///
203    /// FieldElement::conditional_swap(&mut a, &mut b, 1);
204    /// assert_eq!(a, FieldElement::from_u64(20)); // swapped
205    /// assert_eq!(b, FieldElement::from_u64(10)); // swapped
206    /// ```
207    pub fn conditional_swap(a: &mut Self, b: &mut Self, flag: u64) {
208        let mut a_limbs = a.inner.limbs();
209        let mut b_limbs = b.inner.limbs();
210        ct::ct_swap(&mut a_limbs, &mut b_limbs, flag);
211        a.inner = BigInt::from_limbs(&a_limbs);
212        b.inner = BigInt::from_limbs(&b_limbs);
213    }
214
215    /// Check if the value is valid (in range [0, p)).
216    ///
217    /// Returns true if the field element represents a value in [0, p).
218    /// Field elements created through the public API are always valid.
219    ///
220    /// # Examples
221    ///
222    /// ```
223    /// use clock_curve_math::FieldElement;
224    ///
225    /// let element = FieldElement::from_u64(42);
226    /// assert!(element.is_valid());
227    /// ```
228    pub fn is_valid(&self) -> bool {
229        crate::field::helpers::is_valid_field(self)
230    }
231
232    /// Compute the additive inverse (negation).
233    ///
234    /// Returns `-self mod p`, which satisfies `self + (-self) ≡ 0 mod p`.
235    ///
236    /// # Examples
237    ///
238    /// ```
239    /// use clock_curve_math::FieldElement;
240    ///
241    /// let a = FieldElement::from_u64(5);
242    /// let neg_a = a.neg();
243    /// let sum = a.add(&neg_a);
244    /// assert_eq!(sum, FieldElement::from_u64(0));
245    /// ```
246    pub fn neg(&self) -> Self {
247        let zero = Self::from_u64(0);
248        zero.sub(self)
249    }
250
251    /// Get the inner BigInt value (in Montgomery form).
252    ///
253    /// This is primarily used by internal helper functions.
254    pub(crate) fn inner(&self) -> &BigInt {
255        &self.inner
256    }
257}
258
259/// Trait for field element operations.
260///
261/// This trait defines the arithmetic operations available on field elements.
262/// All operations are constant-time and automatically reduce their results
263/// modulo the field prime p = 2^255 - 19.
264pub trait FieldOps {
265    /// Modular addition.
266    ///
267    /// Computes `(self + rhs) mod p` in constant time.
268    ///
269    /// # Examples
270    ///
271    /// ```
272    /// use clock_curve_math::FieldElement;
273    ///
274    /// let a = FieldElement::from_u64(10);
275    /// let b = FieldElement::from_u64(20);
276    /// let sum = a.add(&b);
277    /// assert_eq!(sum, FieldElement::from_u64(30));
278    /// ```
279    fn add(&self, rhs: &Self) -> Self;
280
281    /// Modular subtraction.
282    ///
283    /// Computes `(self - rhs) mod p` in constant time.
284    ///
285    /// # Examples
286    ///
287    /// ```
288    /// use clock_curve_math::FieldElement;
289    ///
290    /// let a = FieldElement::from_u64(20);
291    /// let b = FieldElement::from_u64(10);
292    /// let diff = a.sub(&b);
293    /// assert_eq!(diff, FieldElement::from_u64(10));
294    /// ```
295    fn sub(&self, rhs: &Self) -> Self;
296
297    /// Montgomery multiplication.
298    ///
299    /// Computes `(self * rhs) mod p` using Montgomery arithmetic for efficiency.
300    ///
301    /// # Examples
302    ///
303    /// ```
304    /// use clock_curve_math::FieldElement;
305    ///
306    /// let a = FieldElement::from_u64(10);
307    /// let b = FieldElement::from_u64(20);
308    /// let product = a.mul(&b);
309    /// assert_eq!(product, FieldElement::from_u64(200));
310    /// ```
311    fn mul(&self, rhs: &Self) -> Self;
312
313    /// Squaring (optimized).
314    ///
315    /// Computes `(self * self) mod p`. This is typically faster than general multiplication.
316    ///
317    /// # Examples
318    ///
319    /// ```
320    /// use clock_curve_math::FieldElement;
321    ///
322    /// let a = FieldElement::from_u64(10);
323    /// let square = a.square();
324    /// assert_eq!(square, FieldElement::from_u64(100));
325    /// ```
326    fn square(&self) -> Self;
327
328    /// Constant-time modular inverse.
329    ///
330    /// Computes the modular inverse of `self` modulo p using Fermat's Little Theorem.
331    /// The result satisfies `(self * inv) ≡ 1 mod p`.
332    ///
333    /// # Panics
334    ///
335    /// Panics if `self` is zero (which has no multiplicative inverse).
336    ///
337    /// # Examples
338    ///
339    /// ```
340    /// use clock_curve_math::FieldElement;
341    ///
342    /// let a = FieldElement::from_u64(5);
343    /// let inv = a.inv();
344    /// let product = a.mul(&inv);
345    /// assert_eq!(product, FieldElement::from_u64(1));
346    /// ```
347    fn inv(&self) -> Self;
348
349    /// Modular exponentiation.
350    ///
351    /// Computes `(self ^ exp) mod p` using constant-time exponentiation by squaring.
352    ///
353    /// # Examples
354    ///
355    /// ```
356    /// use clock_curve_math::{FieldElement, BigInt};
357    ///
358    /// let base = FieldElement::from_u64(2);
359    /// let exp = BigInt::from_u64(10);
360    /// let result = base.pow(&exp);
361    /// assert_eq!(result, FieldElement::from_u64(1024)); // 2^10 = 1024
362    /// ```
363    fn pow(&self, exp: &BigInt) -> Self;
364
365    /// Modular exponentiation with input validation.
366    ///
367    /// Computes `(self ^ exp) mod p` using constant-time exponentiation by squaring.
368    /// Validates that the exponent is non-negative.
369    ///
370    /// # Examples
371    ///
372    /// ```
373    /// use clock_curve_math::{FieldElement, BigInt};
374    ///
375    /// let base = FieldElement::from_u64(2);
376    /// let exp = BigInt::from_u64(10);
377    /// let result = base.pow_checked(&exp).unwrap();
378    /// assert_eq!(result, FieldElement::from_u64(1024)); // 2^10 = 1024
379    /// ```
380    ///
381    /// # Errors
382    ///
383    /// Returns [`crate::error::MathError::InvalidExponent`] if the exponent is negative.
384    fn pow_checked(&self, exp: &BigInt) -> Result<Self, crate::error::MathError>
385    where
386        Self: Sized;
387}
388
389impl FieldOps for FieldElement {
390    fn add(&self, rhs: &Self) -> Self {
391        let p = BigInt::from_limbs(&P_LIMBS);
392        let sum = self.inner.add(&rhs.inner);
393
394        // Constant-time reduction: subtract p, then add it back if the result would be negative
395        let diff = sum.sub(&p);
396        let sign_bit = (diff.limbs()[3] >> 63) & 1;
397        let needs_carry = sign_bit; // Add p back if result would be negative
398
399        let mask = ct::ct_mask(needs_carry);
400        let p_masked = BigInt::from_limbs(&[
401            P_LIMBS[0] & mask,
402            P_LIMBS[1] & mask,
403            P_LIMBS[2] & mask,
404            P_LIMBS[3] & mask,
405        ]);
406        let result = diff.add(&p_masked);
407
408        Self { inner: result }
409    }
410
411    fn sub(&self, rhs: &Self) -> Self {
412        let _p = BigInt::from_limbs(&P_LIMBS);
413        let diff = self.inner.sub(&rhs.inner);
414
415        // Constant-time correction: add p if diff is negative (underflow)
416        let is_negative = ct::ct_is_zero(diff.limbs()[3] >> 63) ^ 1; // 1 if MSB is set (negative)
417
418        let mask = ct::ct_mask(is_negative);
419        let p_masked = BigInt::from_limbs(&[
420            P_LIMBS[0] & mask,
421            P_LIMBS[1] & mask,
422            P_LIMBS[2] & mask,
423            P_LIMBS[3] & mask,
424        ]);
425        let result = diff.add(&p_masked);
426
427        Self { inner: result }
428    }
429
430    fn mul(&self, rhs: &Self) -> Self {
431        let p = BigInt::from_limbs(&P_LIMBS);
432        let n_prime = BigInt::from_limbs(&N_PRIME_P);
433        let result = montgomery_mul(&self.inner, &rhs.inner, &p, &n_prime);
434        Self { inner: result }
435    }
436
437    fn square(&self) -> Self {
438        // For now, use the same multiplication. In the future, we could optimize
439        // Montgomery squaring specifically, but the current montgomery_mul
440        // is already quite efficient.
441        self.mul(self)
442    }
443
444    fn inv(&self) -> Self {
445        Self {
446            inner: crate::field::helpers::field_inv(self),
447        }
448    }
449
450    fn pow(&self, exp: &BigInt) -> Self {
451        Self {
452            inner: crate::field::helpers::field_pow(self, exp),
453        }
454    }
455
456    fn pow_checked(&self, exp: &BigInt) -> Result<Self, crate::error::MathError> {
457        crate::validation::validate_exponent(exp)?;
458        Ok(Self {
459            inner: crate::field::helpers::field_pow(self, exp),
460        })
461    }
462}
463
464impl Default for FieldElement {
465    fn default() -> Self {
466        Self::from_u64(0)
467    }
468}