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}