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}