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>
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> {
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: Field + From<u32> + From<u64> + From<u128> + TryFrom<U256> {
326 /// Returns the little-endian representation of the scalar.
327 fn to_le_bytes(&self) -> [u8; 32];
328
329 /// Returns the big-endian representation of the scalar.
330 fn to_be_bytes(&self) -> [u8; 32];
331
332 /// Constructs a scalar from a 512-bit unsigned value, using modular reduction to fit it into
333 /// the scalar range.
334 fn from_u512_mod_n(u512: U512) -> Self;
335
336 /// Constructs a scalar from an [`H512`].
337 ///
338 /// This function works by converting the [`H512`] to a [`U512`] using little-endian byte order
339 /// and then calling [`Self::from_u512_mod_n`].
340 fn from_h512(h512: H512) -> Self;
341
342 /// Returns this scalar as a `u32`, or `None` if the value exceeds the 32-bit range.
343 fn try_to_u32(&self) -> CtOption<u32>;
344
345 /// Returns this scalar as a `u64`, or `None` if the value exceeds the 64-bit range.
346 fn try_to_u64(&self) -> CtOption<u64>;
347
348 /// Returns this scalar as a `u128`, or `None` if the value exceeds the 128-bit range.
349 fn try_to_u128(&self) -> CtOption<u128>;
350
351 /// Returns this scalar as a [`U256`].
352 fn to_u256(&self) -> U256;
353
354 /// Returns this scalar as a [`U512`].
355 fn to_u512(&self) -> U512;
356}
357
358/// A [`Field`] whose order is a prime number.
359///
360/// This kind of field has certain mathematical properties that are very useful in cryptographic
361/// applications. Notably, Fermat's Little Theorem holds.
362pub trait PrimeField: Field {
363 /// The prime order of the field.
364 ///
365 /// Must be consistent with the [`Field::MAX`] constant.
366 const MODULUS: &'static str;
367
368 /// The 2-adicity of the field, which is the exponent of 2 in the factorization of p-1.
369 const S: usize;
370
371 /// A fixed multiplicative generator of `modulus - 1` order. This element must also be a
372 /// quadratic nonresidue.
373 ///
374 /// Implementations of this trait MUST ensure that this is the generator used to derive
375 /// [`Self::ROOT_OF_UNITY`].
376 const MULTIPLICATIVE_GENERATOR: Self;
377
378 /// `p-2`, which is the exponent used for modular inversion on prime fields as per Fermat's
379 /// Little Theorem.
380 const MINUS_TWO: Self;
381
382 /// 2^-1
383 const TWO_INV: Self;
384
385 /// A primitive root of unity.
386 const ROOT_OF_UNITY: Self;
387
388 /// The modular inverse of [`Self::ROOT_OF_UNITY`].
389 const ROOT_OF_UNITY_INV: Self;
390
391 /// Generator of the `t-order` multiplicative subgroup.
392 ///
393 /// It can be calculated by exponentiating [`Self::MULTIPLICATIVE_GENERATOR`] by `2^s`, where
394 /// `s` is [`Self::S`].
395 const DELTA: Self;
396}
397
398/// A ~64-bit prime field.
399pub trait PrimeField64: Field64 + PrimeField {}
400
401/// A ~256-bit prime field.
402pub trait PrimeField256: Field256 + PrimeField {}