Skip to main content

starkom_ff/
fields.rs

1use primitive_types::{H512, U256, U512};
2use rand_core::{CryptoRng, TryCryptoRng};
3use std::fmt::{Binary, Debug, Display, LowerHex, Octal, UpperHex};
4use std::iter::{Product, Sum};
5use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
6use std::str::FromStr;
7use subtle::{
8    Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
9    CtOption,
10};
11
12/// A finite field.
13///
14/// NOTE: this is assumed to be a *numeric* finite field, ie. a range of the integers from 0
15/// inclusive to N exclusive, with N being the cardinality of the field. For this reason this trait
16/// inherits several traits that are not necessarily part of algebraic fields, such as [`Ord`] for
17/// total ordering and several `std::fmt::*` traits for formatting numbers.
18pub trait Field:
19    'static
20    + Debug
21    + Default
22    + Sized
23    + Send
24    + Sync
25    + Copy
26    + Clone
27    + Eq
28    + Ord
29    + ConstantTimeEq
30    + ConstantTimeGreater
31    + ConstantTimeLess
32    + ConditionallySelectable
33    + Add<Output = Self>
34    + for<'a> Add<&'a Self, Output = Self>
35    + AddAssign<Self>
36    + for<'a> AddAssign<&'a Self>
37    + Neg<Output = Self>
38    + Sub<Output = Self>
39    + for<'a> Sub<&'a Self, Output = Self>
40    + SubAssign<Self>
41    + for<'a> SubAssign<&'a Self>
42    + Mul<Output = Self>
43    + for<'a> Mul<&'a Self, Output = Self>
44    + MulAssign<Self>
45    + for<'a> MulAssign<&'a Self>
46    + Div<Output = Self>
47    + for<'a> Div<&'a Self, Output = Self>
48    + DivAssign<Self>
49    + for<'a> DivAssign<&'a Self>
50    + Sum
51    + Product
52    + Display
53    + Binary
54    + Octal
55    + LowerHex
56    + UpperHex
57    + FromStr
58    + From<u8>
59    + From<u16>
60    + TryFrom<usize, Error: Debug>
61{
62    /// The number of bytes required to represent a value.
63    const LEN: usize;
64
65    /// The number of bits required to represent a value.
66    const NUM_BITS: usize = Self::LEN * 8;
67
68    /// Same as [`Self::NUM_BITS`]. Provided for consistency with native Rust types.
69    const BITS: usize = Self::NUM_BITS;
70
71    /// The additive identity element.
72    const ZERO: Self;
73
74    /// The multiplicative identity element.
75    const ONE: Self;
76
77    /// The largest value in the field.
78    const MAX: Self;
79
80    /// Returns the element zero.
81    fn zero() -> Self {
82        Self::ZERO
83    }
84
85    /// Returns the element one.
86    fn one() -> Self {
87        Self::ONE
88    }
89
90    /// Compares with zero.
91    fn is_zero(&self) -> Choice {
92        self.ct_eq(&Self::ZERO)
93    }
94
95    /// Returns true iff the value is even.
96    fn is_even(&self) -> Choice {
97        !self.is_odd()
98    }
99
100    /// Returns true iff the value is odd.
101    fn is_odd(&self) -> Choice;
102
103    /// Picks a uniformly distributed random scalar securely from the provided fallible CSPRNG.
104    fn try_random<R: TryCryptoRng>(rng: &mut R) -> Result<Self, R::Error>;
105
106    /// Picks a uniformly distributed random scalar securely from the provided infallible CSPRNG.
107    fn random<R: CryptoRng>(rng: &mut R) -> Self;
108
109    /// Picks a uniformly distributed random scalar securely from the system's default CSPRNG.
110    fn random_default() -> Self;
111
112    /// Returns this value doubled. `self` remains unchanged.
113    fn double(&self) -> Self {
114        self.add(self)
115    }
116
117    /// Returns this value squared. `self` remains unchanged.
118    fn square(&self) -> Self {
119        self.mul(self)
120    }
121
122    /// Returns this value raised to 3. `self` remains unchanged.
123    fn cube(&self) -> Self {
124        self.square() * self
125    }
126
127    /// Returns the modular inverse of `self, or `None` if `self` is zero.
128    fn invert(&self) -> CtOption<Self>;
129
130    /// Returns the modular inverse of `self`, assuming `self` is not zero and panicking otherwise.
131    fn invert_unwrap(&self) -> Self {
132        self.invert().unwrap()
133    }
134
135    /// Returns the modular inverse of `self`, or zero if `self` is zero.
136    fn invert_or_zero(&self) -> Self {
137        self.invert().unwrap_or(Self::ZERO)
138    }
139
140    /// Returns the modular inverse of `self, or `None` if `self` is zero.
141    fn invert_vartime(&self) -> Option<Self>;
142
143    /// Raises this value to `exp`, running exactly [`Self::NUM_BITS`] squares and multiplications
144    /// so that a time observer cannot infer the exponent.
145    fn pow(self, exp: Self) -> Self;
146
147    /// Raises this value to `exp`.
148    fn pow_vartime(self, exp: Self) -> Self;
149
150    /// Raises this value to `exp`, running exactly [`usize::BITS`] squares and multiplications so
151    /// that a time observer cannot infer the exponent.
152    ///
153    /// Unlike [`Field::pow`], `exp` is a `usize`. That makes the algorithm significantly faster
154    /// because the square-and-multiply loop runs only [`usize::BITS`] times rather than
155    /// [`Field::BITS`] times, and bitwise operations on the exponent are native.
156    fn pow_small(mut self, mut exp: usize) -> Self {
157        let mut result = Self::ONE;
158        for _ in 0..usize::BITS {
159            let product = result * self;
160            result = Self::conditional_select(&result, &product, Choice::from((exp & 1) as u8));
161            exp >>= 1;
162            self = self.square();
163        }
164        result
165    }
166
167    /// Raises this value to `exp`.
168    ///
169    /// Unlike [`Field::pow`], `exp` is a `usize`. That makes the algorithm significantly faster
170    /// because bitwise operations on the exponent are native.
171    fn pow_small_vartime(mut self, mut exp: usize) -> Self {
172        let mut result = Self::ONE;
173        while exp != 0 {
174            if (exp & 1) != 0 {
175                result *= self;
176            }
177            exp >>= 1;
178            self = self.square();
179        }
180        result
181    }
182
183    /// Raises this value to `exp`, running exactly [`u32::BITS`] squares and multiplications so
184    /// that an observer cannot infer the exponent.
185    ///
186    /// Unlike [`Field::pow`], `exp` is a `u32`. That makes the algorithm significantly faster
187    /// because the square-and-multiply loop runs only 32 times rather than [`Field::BITS`] times,
188    /// and bitwise operations on the exponent are native.
189    fn pow_u32(mut self, mut exp: u32) -> Self {
190        let mut result = Self::ONE;
191        for _ in 0..u32::BITS {
192            let product = result * self;
193            result = Self::conditional_select(&result, &product, Choice::from((exp & 1) as u8));
194            exp >>= 1;
195            self = self.square();
196        }
197        result
198    }
199
200    /// Raises this value to `exp`.
201    ///
202    /// Unlike [`Field::pow_vartime`], `exp` is a `u32`. That makes the algorithm significantly
203    /// faster because bitwise operations on the exponent are native.
204    fn pow_u32_vartime(mut self, mut exp: u32) -> Self {
205        let mut result = Self::ONE;
206        while exp != 0 {
207            if (exp & 1) != 0 {
208                result *= self;
209            }
210            exp >>= 1;
211            self = self.square();
212        }
213        result
214    }
215
216    /// Raises this value to `exp`, running exactly [`u64::BITS`] squares and multiplications so
217    /// that an observer cannot infer the exponent.
218    ///
219    /// Unlike [`Field::pow`], `exp` is a `u64`. That makes the algorithm significantly faster
220    /// because the square-and-multiply loop runs only 64 times rather than [`Field::BITS`] times,
221    /// and bitwise operations on the exponent are native.
222    fn pow_u64(mut self, mut exp: u64) -> Self {
223        let mut result = Self::ONE;
224        for _ in 0..u64::BITS {
225            let product = result * self;
226            result = Self::conditional_select(&result, &product, Choice::from((exp & 1) as u8));
227            exp >>= 1;
228            self = self.square();
229        }
230        result
231    }
232
233    /// Raises this value to `exp`.
234    ///
235    /// Unlike [`Field::pow_vartime`], `exp` is a `u64`. That makes the algorithm significantly
236    /// faster because bitwise operations on the exponent are native.
237    fn pow_u64_vartime(mut self, mut exp: u64) -> Self {
238        let mut result = Self::ONE;
239        while exp != 0 {
240            if (exp & 1) != 0 {
241                result *= self;
242            }
243            exp >>= 1;
244            self = self.square();
245        }
246        result
247    }
248
249    /// Performs integer division by `rhs` and returns a (quotient, remainder) pair. Panics if `rhs`
250    /// is zero.
251    fn div_int(&self, rhs: &Self) -> (Self, Self);
252
253    /// Constructs a scalar from the little-endian byte representation of an integer.
254    ///
255    /// The provided slice must have exactly [`Self::LEN`] bytes.
256    ///
257    /// The function returns `None` if the integer lies outside the field range.
258    fn try_from_le_bytes(bytes: &[u8]) -> CtOption<Self>;
259
260    /// Constructs a scalar from the big-endian byte representation of an integer.
261    ///
262    /// The provided slice must have exactly [`Self::LEN`] bytes.
263    ///
264    /// The function returns `None` if the integer lies outside the field range.
265    fn try_from_be_bytes(bytes: &[u8]) -> CtOption<Self>;
266
267    /// Parses a scalar from its text representation in the given `radix`.
268    ///
269    /// Returns an error on invalid format or overflow. Panics if `radix` is less than 2 or greater
270    /// than 36.
271    fn from_str_radix(s: &str, radix: usize) -> Result<Self, std::fmt::Error>;
272
273    /// Converts a scalar to its textual representation in the given `radix`.
274    ///
275    /// The returned string will have at least `pad_to` characters, and will be padded with zeros if
276    /// necessary.
277    ///
278    /// When `radix` is greater than 10, the representation will start using alphabetic characters
279    /// from A to Z for digits greater than 9, e.g. character A to F for hexadecimal numbers. The
280    /// `upper_case` flag specifies whether those characters must be lower case or upper case.
281    ///
282    /// This function panics if `radix` is less than 2 or greater than 36.
283    fn to_str_radix(&self, radix: usize, pad_to: usize, upper_case: bool) -> String;
284
285    /// Returns this scalar as a `u8`, or `None` if the value exceeds the 8-bit range.
286    fn try_to_u8(&self) -> Option<u8>;
287
288    /// Returns this scalar as a `u16`, or `None` if the value exceeds the 16-bit range.
289    fn try_to_u16(&self) -> Option<u16>;
290}
291
292/// A ~64-bit [`Field`].
293pub trait Field64: Field + From<u32> + TryFrom<u64, Error: Debug> {
294    /// Returns the little-endian representation of the scalar.
295    fn to_le_bytes(&self) -> [u8; 8];
296
297    /// Returns the big-endian representation of the scalar.
298    fn to_be_bytes(&self) -> [u8; 8];
299
300    /// Constructs a scalar from a 128-bit unsigned value, using modular reduction to fit it into
301    /// the scalar range.
302    fn from_u128_mod_n(u128: u128) -> Self;
303
304    /// Constructs a scalar from a 256-bit unsigned value, using modular reduction to fit it into
305    /// the scalar range.
306    fn from_u256_mod_n(u256: U256) -> Self;
307
308    /// Returns this scalar as a `u32`, or `None` if the value exceeds the 32-bit range.
309    fn try_to_u32(&self) -> CtOption<u32>;
310
311    /// Converts the scalar to a 64-bit unsigned integer.
312    fn to_u64(&self) -> u64;
313
314    /// Converts the scalar to a 128-bit unsigned integer.
315    fn to_u128(&self) -> u128;
316
317    /// Converts the scalar to a 256-bit unsigned integer.
318    fn to_u256(&self) -> U256;
319
320    /// Converts the scalar to a 512-bit unsigned integer.
321    fn to_u512(&self) -> U512;
322}
323
324/// A ~256-bit [`Field`].
325pub trait Field256:
326    Field + From<u32> + From<u64> + From<u128> + TryFrom<U256, Error: Debug>
327{
328    /// Returns the little-endian representation of the scalar.
329    fn to_le_bytes(&self) -> [u8; 32];
330
331    /// Returns the big-endian representation of the scalar.
332    fn to_be_bytes(&self) -> [u8; 32];
333
334    /// Constructs a scalar from a 512-bit unsigned value, using modular reduction to fit it into
335    /// the scalar range.
336    fn from_u512_mod_n(u512: U512) -> Self;
337
338    /// Constructs a scalar from an [`H512`].
339    ///
340    /// This function works by converting the [`H512`] to a [`U512`] using little-endian byte order
341    /// and then calling [`Self::from_u512_mod_n`].
342    fn from_h512(h512: H512) -> Self;
343
344    /// Returns this scalar as a `u32`, or `None` if the value exceeds the 32-bit range.
345    fn try_to_u32(&self) -> CtOption<u32>;
346
347    /// Returns this scalar as a `u64`, or `None` if the value exceeds the 64-bit range.
348    fn try_to_u64(&self) -> CtOption<u64>;
349
350    /// Returns this scalar as a `u128`, or `None` if the value exceeds the 128-bit range.
351    fn try_to_u128(&self) -> CtOption<u128>;
352
353    /// Returns this scalar as a [`U256`].
354    fn to_u256(&self) -> U256;
355
356    /// Returns this scalar as a [`U512`].
357    fn to_u512(&self) -> U512;
358}
359
360/// A [`Field`] whose order is a prime number.
361///
362/// This kind of field has certain mathematical properties that are very useful in cryptographic
363/// applications. Notably, Fermat's Little Theorem holds.
364pub trait PrimeField: Field {
365    /// The prime order of the field.
366    ///
367    /// Must be consistent with the [`Field::MAX`] constant.
368    const MODULUS: &'static str;
369
370    /// The 2-adicity of the field, which is the exponent of 2 in the factorization of p-1.
371    const S: usize;
372
373    /// A fixed multiplicative generator of `modulus - 1` order. This element must also be a
374    /// quadratic nonresidue.
375    ///
376    /// Implementations of this trait MUST ensure that this is the generator used to derive
377    /// [`Self::ROOT_OF_UNITY`].
378    const MULTIPLICATIVE_GENERATOR: Self;
379
380    /// `p-2`, which is the exponent used for modular inversion on prime fields as per Fermat's
381    /// Little Theorem.
382    const MINUS_TWO: Self;
383
384    /// 2^-1
385    const TWO_INV: Self;
386
387    /// A primitive root of unity.
388    const ROOT_OF_UNITY: Self;
389
390    /// The modular inverse of [`Self::ROOT_OF_UNITY`].
391    const ROOT_OF_UNITY_INV: Self;
392
393    /// Generator of the `t-order` multiplicative subgroup.
394    ///
395    /// It can be calculated by exponentiating [`Self::MULTIPLICATIVE_GENERATOR`] by `2^s`, where
396    /// `s` is [`Self::S`].
397    const DELTA: Self;
398}
399
400/// A ~64-bit prime field.
401pub trait PrimeField64: Field64 + PrimeField {}
402
403/// A ~256-bit prime field.
404pub trait PrimeField256: Field256 + PrimeField {}