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    /// Inverts all the provided values in place using Montgomery batch inversion.
144    ///
145    /// As with [`Self::invert_unwrap`], this function panics if any of the `values` is zero.
146    fn invert_batch(values: &mut [Self]) {
147        let length = values.len();
148        let mut partial_products = vec![Self::ONE; length];
149        let mut accumulator = Self::ONE;
150        for i in 0..length {
151            partial_products[i] = accumulator;
152            accumulator *= values[i];
153        }
154        let mut inverse = accumulator.invert_unwrap();
155        for i in (0..length).rev() {
156            let input = values[i];
157            values[i] = partial_products[i] * inverse;
158            inverse *= input;
159        }
160    }
161
162    /// Vartime version of [`Self::invert_batch`].
163    fn invert_batch_vartime(values: &mut [Self]) {
164        let length = values.len();
165        let mut partial_products = vec![Self::ONE; length];
166        let mut accumulator = Self::ONE;
167        for i in 0..length {
168            partial_products[i] = accumulator;
169            accumulator *= values[i];
170        }
171        let mut inverse = accumulator.invert_vartime().unwrap();
172        for i in (0..length).rev() {
173            let input = values[i];
174            values[i] = partial_products[i] * inverse;
175            inverse *= input;
176        }
177    }
178
179    /// Raises this value to `exp`, running exactly [`Self::NUM_BITS`] squares and multiplications
180    /// so that a time observer cannot infer the exponent.
181    fn pow(self, exp: Self) -> Self;
182
183    /// Raises this value to `exp`.
184    fn pow_vartime(self, exp: Self) -> Self;
185
186    /// Raises this value to `exp`, running exactly [`usize::BITS`] squares and multiplications so
187    /// that a time observer cannot infer the exponent.
188    ///
189    /// Unlike [`Field::pow`], `exp` is a `usize`. That makes the algorithm significantly faster
190    /// because the square-and-multiply loop runs only [`usize::BITS`] times rather than
191    /// [`Field::BITS`] times, and bitwise operations on the exponent are native.
192    fn pow_small(mut self, mut exp: usize) -> Self {
193        let mut result = Self::ONE;
194        for _ in 0..usize::BITS {
195            let product = result * self;
196            result = Self::conditional_select(&result, &product, Choice::from((exp & 1) as u8));
197            exp >>= 1;
198            self = self.square();
199        }
200        result
201    }
202
203    /// Raises this value to `exp`.
204    ///
205    /// Unlike [`Field::pow`], `exp` is a `usize`. That makes the algorithm significantly faster
206    /// because bitwise operations on the exponent are native.
207    fn pow_small_vartime(mut self, mut exp: usize) -> Self {
208        let mut result = Self::ONE;
209        while exp != 0 {
210            if (exp & 1) != 0 {
211                result *= self;
212            }
213            exp >>= 1;
214            self = self.square();
215        }
216        result
217    }
218
219    /// Raises this value to `exp`, running exactly [`u32::BITS`] squares and multiplications so
220    /// that an observer cannot infer the exponent.
221    ///
222    /// Unlike [`Field::pow`], `exp` is a `u32`. That makes the algorithm significantly faster
223    /// because the square-and-multiply loop runs only 32 times rather than [`Field::BITS`] times,
224    /// and bitwise operations on the exponent are native.
225    fn pow_u32(mut self, mut exp: u32) -> Self {
226        let mut result = Self::ONE;
227        for _ in 0..u32::BITS {
228            let product = result * self;
229            result = Self::conditional_select(&result, &product, Choice::from((exp & 1) as u8));
230            exp >>= 1;
231            self = self.square();
232        }
233        result
234    }
235
236    /// Raises this value to `exp`.
237    ///
238    /// Unlike [`Field::pow_vartime`], `exp` is a `u32`. That makes the algorithm significantly
239    /// faster because bitwise operations on the exponent are native.
240    fn pow_u32_vartime(mut self, mut exp: u32) -> Self {
241        let mut result = Self::ONE;
242        while exp != 0 {
243            if (exp & 1) != 0 {
244                result *= self;
245            }
246            exp >>= 1;
247            self = self.square();
248        }
249        result
250    }
251
252    /// Raises this value to `exp`, running exactly [`u64::BITS`] squares and multiplications so
253    /// that an observer cannot infer the exponent.
254    ///
255    /// Unlike [`Field::pow`], `exp` is a `u64`. That makes the algorithm significantly faster
256    /// because the square-and-multiply loop runs only 64 times rather than [`Field::BITS`] times,
257    /// and bitwise operations on the exponent are native.
258    fn pow_u64(mut self, mut exp: u64) -> Self {
259        let mut result = Self::ONE;
260        for _ in 0..u64::BITS {
261            let product = result * self;
262            result = Self::conditional_select(&result, &product, Choice::from((exp & 1) as u8));
263            exp >>= 1;
264            self = self.square();
265        }
266        result
267    }
268
269    /// Raises this value to `exp`.
270    ///
271    /// Unlike [`Field::pow_vartime`], `exp` is a `u64`. That makes the algorithm significantly
272    /// faster because bitwise operations on the exponent are native.
273    fn pow_u64_vartime(mut self, mut exp: u64) -> Self {
274        let mut result = Self::ONE;
275        while exp != 0 {
276            if (exp & 1) != 0 {
277                result *= self;
278            }
279            exp >>= 1;
280            self = self.square();
281        }
282        result
283    }
284
285    /// Performs integer division by `rhs` and returns a (quotient, remainder) pair. Panics if `rhs`
286    /// is zero.
287    fn div_int(&self, rhs: &Self) -> (Self, Self);
288
289    /// Constructs a scalar from the little-endian byte representation of an integer.
290    ///
291    /// The provided slice must have exactly [`Self::LEN`] bytes.
292    ///
293    /// The function returns `None` if the integer lies outside the field range.
294    fn try_from_le_bytes(bytes: &[u8]) -> CtOption<Self>;
295
296    /// Constructs a scalar from the big-endian byte representation of an integer.
297    ///
298    /// The provided slice must have exactly [`Self::LEN`] bytes.
299    ///
300    /// The function returns `None` if the integer lies outside the field range.
301    fn try_from_be_bytes(bytes: &[u8]) -> CtOption<Self>;
302
303    /// Parses a scalar from its text representation in the given `radix`.
304    ///
305    /// Returns an error on invalid format or overflow. Panics if `radix` is less than 2 or greater
306    /// than 36.
307    fn from_str_radix(s: &str, radix: usize) -> Result<Self, std::fmt::Error>;
308
309    /// Converts a scalar to its textual representation in the given `radix`.
310    ///
311    /// The returned string will have at least `pad_to` characters, and will be padded with zeros if
312    /// necessary.
313    ///
314    /// When `radix` is greater than 10, the representation will start using alphabetic characters
315    /// from A to Z for digits greater than 9, e.g. character A to F for hexadecimal numbers. The
316    /// `upper_case` flag specifies whether those characters must be lower case or upper case.
317    ///
318    /// This function panics if `radix` is less than 2 or greater than 36.
319    fn to_str_radix(&self, radix: usize, pad_to: usize, upper_case: bool) -> String;
320
321    /// Returns this scalar as a `u8`, or `None` if the value exceeds the 8-bit range.
322    fn try_to_u8(&self) -> Option<u8>;
323
324    /// Returns this scalar as a `u16`, or `None` if the value exceeds the 16-bit range.
325    fn try_to_u16(&self) -> Option<u16>;
326}
327
328/// A ~64-bit [`Field`].
329pub trait Field64: Field + From<u32> + TryFrom<u64, Error: Debug> {
330    /// Returns the little-endian representation of the scalar.
331    fn to_le_bytes(&self) -> [u8; 8];
332
333    /// Returns the big-endian representation of the scalar.
334    fn to_be_bytes(&self) -> [u8; 8];
335
336    /// Constructs a scalar from a 128-bit unsigned value, using modular reduction to fit it into
337    /// the scalar range.
338    fn from_u128_mod_n(u128: u128) -> Self;
339
340    /// Constructs a scalar from a 256-bit unsigned value, using modular reduction to fit it into
341    /// the scalar range.
342    fn from_u256_mod_n(u256: U256) -> 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    /// Converts the scalar to a 64-bit unsigned integer.
348    fn to_u64(&self) -> u64;
349
350    /// Converts the scalar to a 128-bit unsigned integer.
351    fn to_u128(&self) -> u128;
352
353    /// Converts the scalar to a 256-bit unsigned integer.
354    fn to_u256(&self) -> U256;
355
356    /// Converts the scalar to a 512-bit unsigned integer.
357    fn to_u512(&self) -> U512;
358}
359
360/// A ~256-bit [`Field`].
361pub trait Field256:
362    Field + From<u32> + From<u64> + From<u128> + TryFrom<U256, Error: Debug>
363{
364    /// Returns the little-endian representation of the scalar.
365    fn to_le_bytes(&self) -> [u8; 32];
366
367    /// Returns the big-endian representation of the scalar.
368    fn to_be_bytes(&self) -> [u8; 32];
369
370    /// Constructs a scalar from a 512-bit unsigned value, using modular reduction to fit it into
371    /// the scalar range.
372    fn from_u512_mod_n(u512: U512) -> Self;
373
374    /// Constructs a scalar from an [`H512`].
375    ///
376    /// This function works by converting the [`H512`] to a [`U512`] using little-endian byte order
377    /// and then calling [`Self::from_u512_mod_n`].
378    fn from_h512(h512: H512) -> Self;
379
380    /// Returns this scalar as a `u32`, or `None` if the value exceeds the 32-bit range.
381    fn try_to_u32(&self) -> CtOption<u32>;
382
383    /// Returns this scalar as a `u64`, or `None` if the value exceeds the 64-bit range.
384    fn try_to_u64(&self) -> CtOption<u64>;
385
386    /// Returns this scalar as a `u128`, or `None` if the value exceeds the 128-bit range.
387    fn try_to_u128(&self) -> CtOption<u128>;
388
389    /// Returns this scalar as a [`U256`].
390    fn to_u256(&self) -> U256;
391
392    /// Returns this scalar as a [`U512`].
393    fn to_u512(&self) -> U512;
394}
395
396/// A [`Field`] whose order is a prime number.
397///
398/// This kind of field has certain mathematical properties that are very useful in cryptographic
399/// applications. Notably, Fermat's Little Theorem holds.
400pub trait PrimeField: Field {
401    /// The prime order of the field.
402    ///
403    /// Must be consistent with the [`Field::MAX`] constant.
404    const MODULUS: &'static str;
405
406    /// The 2-adicity of the field, which is the exponent of 2 in the factorization of p-1.
407    const S: usize;
408
409    /// A fixed multiplicative generator of `modulus - 1` order. This element must also be a
410    /// quadratic nonresidue.
411    ///
412    /// Implementations of this trait MUST ensure that this is the generator used to derive
413    /// [`Self::ROOT_OF_UNITY`].
414    const MULTIPLICATIVE_GENERATOR: Self;
415
416    /// `p-2`, which is the exponent used for modular inversion on prime fields as per Fermat's
417    /// Little Theorem.
418    const MINUS_TWO: Self;
419
420    /// 2^-1
421    const TWO_INV: Self;
422
423    /// A primitive root of unity.
424    const ROOT_OF_UNITY: Self;
425
426    /// The modular inverse of [`Self::ROOT_OF_UNITY`].
427    const ROOT_OF_UNITY_INV: Self;
428
429    /// Generator of the `t-order` multiplicative subgroup.
430    ///
431    /// It can be calculated by exponentiating [`Self::MULTIPLICATIVE_GENERATOR`] by `2^s`, where
432    /// `s` is [`Self::S`].
433    const DELTA: Self;
434}
435
436/// A ~64-bit prime field.
437pub trait PrimeField64: Field64 + PrimeField {}
438
439/// A ~256-bit prime field.
440pub trait PrimeField256: Field256 + PrimeField {}
441
442/// Describes a prime field with a (3^T)-th root of unity.
443pub trait ThreeAdicField: PrimeField {
444    /// The 3-adicity of the field.
445    const T: usize;
446
447    /// Inverse of 3 in the field.
448    const THREE_INV: Self;
449
450    /// The primitive 3-adic root of unity, a number w such that w^(3^T) = 1.
451    const THREE_ADIC_ROOT_OF_UNITY: Self;
452
453    /// The inverse of the root of unity.
454    const THREE_ADIC_ROOT_OF_UNITY_INV: Self;
455}