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}