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}