diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
commit | 837b550238aa671a591ccf282dddeab29cadb206 (patch) | |
tree | 914b6b8862bace72bd3245ca184d374b08d8a672 /vendor/ff/src | |
parent | Adding debian version 1.70.0+dfsg2-1. (diff) | |
download | rustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz rustc-837b550238aa671a591ccf282dddeab29cadb206.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ff/src')
-rw-r--r-- | vendor/ff/src/batch.rs | 18 | ||||
-rw-r--r-- | vendor/ff/src/helpers.rs | 128 | ||||
-rw-r--r-- | vendor/ff/src/lib.rs | 256 |
3 files changed, 365 insertions, 37 deletions
diff --git a/vendor/ff/src/batch.rs b/vendor/ff/src/batch.rs index c479f9d49..96ddc5a97 100644 --- a/vendor/ff/src/batch.rs +++ b/vendor/ff/src/batch.rs @@ -31,19 +31,19 @@ where I: IntoIterator<Item = &'a mut F>, { fn batch_invert(self) -> F { - let mut acc = F::one(); + let mut acc = F::ONE; let iter = self.into_iter(); let mut tmp = alloc::vec::Vec::with_capacity(iter.size_hint().0); for p in iter { let q = *p; tmp.push((acc, p)); - acc = F::conditional_select(&(acc * q), &acc, q.ct_eq(&F::zero())); + acc = F::conditional_select(&(acc * q), &acc, q.is_zero()); } acc = acc.invert().unwrap(); let allinv = acc; for (tmp, p) in tmp.into_iter().rev() { - let skip = p.ct_eq(&F::zero()); + let skip = p.is_zero(); let tmp = tmp * acc; acc = F::conditional_select(&(acc * *p), &acc, skip); @@ -74,17 +74,17 @@ impl BatchInverter { { assert_eq!(elements.len(), scratch_space.len()); - let mut acc = F::one(); + let mut acc = F::ONE; for (p, scratch) in elements.iter().zip(scratch_space.iter_mut()) { *scratch = acc; - acc = F::conditional_select(&(acc * *p), &acc, p.ct_eq(&F::zero())); + acc = F::conditional_select(&(acc * *p), &acc, p.is_zero()); } acc = acc.invert().unwrap(); let allinv = acc; for (p, scratch) in elements.iter_mut().zip(scratch_space.iter()).rev() { let tmp = *scratch * acc; - let skip = p.ct_eq(&F::zero()); + let skip = p.is_zero(); acc = F::conditional_select(&(acc * *p), &acc, skip); *p = F::conditional_select(&tmp, &p, skip); } @@ -109,11 +109,11 @@ impl BatchInverter { TE: Fn(&mut T) -> &mut F, TS: Fn(&mut T) -> &mut F, { - let mut acc = F::one(); + let mut acc = F::ONE; for item in items.iter_mut() { *(scratch_space)(item) = acc; let p = (element)(item); - acc = F::conditional_select(&(acc * *p), &acc, p.ct_eq(&F::zero())); + acc = F::conditional_select(&(acc * *p), &acc, p.is_zero()); } acc = acc.invert().unwrap(); let allinv = acc; @@ -121,7 +121,7 @@ impl BatchInverter { for item in items.iter_mut().rev() { let tmp = *(scratch_space)(item) * acc; let p = (element)(item); - let skip = p.ct_eq(&F::zero()); + let skip = p.is_zero(); acc = F::conditional_select(&(acc * *p), &acc, skip); *p = F::conditional_select(&tmp, &p, skip); } diff --git a/vendor/ff/src/helpers.rs b/vendor/ff/src/helpers.rs new file mode 100644 index 000000000..d1d6371dd --- /dev/null +++ b/vendor/ff/src/helpers.rs @@ -0,0 +1,128 @@ +//! Helper methods for implementing the `ff` traits. + +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; + +use crate::PrimeField; + +/// Constant-time implementation of Tonelli–Shanks' square-root algorithm for +/// `p mod 16 = 1`. +/// +/// `tm1d2` should be set to `(t - 1) // 2`, where `t = (modulus - 1) >> F::S`. +/// +/// ## Implementing [`Field::sqrt`] +/// +/// This function can be used to implement [`Field::sqrt`] for fields that both implement +/// [`PrimeField`] and satisfy `p mod 16 = 1`. +/// +/// [`Field::sqrt`]: crate::Field::sqrt +pub fn sqrt_tonelli_shanks<F: PrimeField, S: AsRef<[u64]>>(f: &F, tm1d2: S) -> CtOption<F> { + // This is a constant-time version of https://eprint.iacr.org/2012/685.pdf (page 12, + // algorithm 5). Steps 2-5 of the algorithm are omitted because they are only needed + // to detect non-square input; it is more efficient to do that by checking at the end + // whether the square of the result is the input. + + // w = self^((t - 1) // 2) + let w = f.pow_vartime(tm1d2); + + let mut v = F::S; + let mut x = w * f; + let mut b = x * w; + + // Initialize z as the 2^S root of unity. + let mut z = F::ROOT_OF_UNITY; + + for max_v in (1..=F::S).rev() { + let mut k = 1; + let mut b2k = b.square(); + let mut j_less_than_v: Choice = 1.into(); + + // This loop has three phases based on the value of k for algorithm 5: + // - for j <= k, we square b2k in order to calculate b^{2^k}. + // - for k < j <= v, we square z in order to calculate ω. + // - for j > v, we do nothing. + for j in 2..max_v { + let b2k_is_one = b2k.ct_eq(&F::ONE); + let squared = F::conditional_select(&b2k, &z, b2k_is_one).square(); + b2k = F::conditional_select(&squared, &b2k, b2k_is_one); + let new_z = F::conditional_select(&z, &squared, b2k_is_one); + j_less_than_v &= !j.ct_eq(&v); + k = u32::conditional_select(&j, &k, b2k_is_one); + z = F::conditional_select(&z, &new_z, j_less_than_v); + } + + let result = x * z; + x = F::conditional_select(&result, &x, b.ct_eq(&F::ONE)); + z = z.square(); + b *= z; + v = k; + } + + CtOption::new( + x, + (x * x).ct_eq(f), // Only return Some if it's the square root. + ) +} + +/// Computes: +/// +/// - $(\textsf{true}, \sqrt{\textsf{num}/\textsf{div}})$, if $\textsf{num}$ and +/// $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is a square in the +/// field; +/// - $(\textsf{true}, 0)$, if $\textsf{num}$ is zero; +/// - $(\textsf{false}, 0)$, if $\textsf{num}$ is nonzero and $\textsf{div}$ is zero; +/// - $(\textsf{false}, \sqrt{G_S \cdot \textsf{num}/\textsf{div}})$, if +/// $\textsf{num}$ and $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is +/// a nonsquare in the field; +/// +/// where $G_S$ is a non-square. +/// +/// For this method, $G_S$ is currently [`PrimeField::ROOT_OF_UNITY`], a generator of the +/// order $2^S$ subgroup. Users of this crate should not rely on this generator being +/// fixed; it may be changed in future crate versions to simplify the implementation of +/// the SSWU hash-to-curve algorithm. +/// +/// The choice of root from sqrt is unspecified. +/// +/// ## Implementing [`Field::sqrt_ratio`] +/// +/// This function can be used to implement [`Field::sqrt_ratio`] for fields that also +/// implement [`PrimeField`]. If doing so, the default implementation of [`Field::sqrt`] +/// *MUST* be overridden, or else both functions will recurse in a cycle until a stack +/// overflow occurs. +/// +/// [`Field::sqrt_ratio`]: crate::Field::sqrt_ratio +/// [`Field::sqrt`]: crate::Field::sqrt +pub fn sqrt_ratio_generic<F: PrimeField>(num: &F, div: &F) -> (Choice, F) { + // General implementation: + // + // a = num * inv0(div) + // = { 0 if div is zero + // { num/div otherwise + // + // b = G_S * a + // = { 0 if div is zero + // { G_S*num/div otherwise + // + // Since G_S is non-square, a and b are either both zero (and both square), or + // only one of them is square. We can therefore choose the square root to return + // based on whether a is square, but for the boolean output we need to handle the + // num != 0 && div == 0 case specifically. + + let a = div.invert().unwrap_or(F::ZERO) * num; + let b = a * F::ROOT_OF_UNITY; + let sqrt_a = a.sqrt(); + let sqrt_b = b.sqrt(); + + let num_is_zero = num.is_zero(); + let div_is_zero = div.is_zero(); + let is_square = sqrt_a.is_some(); + let is_nonsquare = sqrt_b.is_some(); + assert!(bool::from( + num_is_zero | div_is_zero | (is_square ^ is_nonsquare) + )); + + ( + is_square & (num_is_zero | !div_is_zero), + CtOption::conditional_select(&sqrt_b, &sqrt_a, is_square).unwrap(), + ) +} diff --git a/vendor/ff/src/lib.rs b/vendor/ff/src/lib.rs index 4ccd0de87..96bd3e966 100644 --- a/vendor/ff/src/lib.rs +++ b/vendor/ff/src/lib.rs @@ -12,6 +12,8 @@ extern crate alloc; mod batch; pub use batch::*; +pub mod helpers; + #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub use ff_derive::PrimeField; @@ -22,8 +24,11 @@ pub use bitvec::view::BitViewSized; #[cfg(feature = "bits")] use bitvec::{array::BitArray, order::Lsb0}; + use core::fmt; +use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; + use rand_core::RngCore; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; @@ -45,32 +50,36 @@ pub trait Field: + 'static + ConditionallySelectable + ConstantTimeEq + + Neg<Output = Self> + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self> - + Neg<Output = Self> + + Sum + + Product + for<'a> Add<&'a Self, Output = Self> - + for<'a> Mul<&'a Self, Output = Self> + for<'a> Sub<&'a Self, Output = Self> - + MulAssign + + for<'a> Mul<&'a Self, Output = Self> + + for<'a> Sum<&'a Self> + + for<'a> Product<&'a Self> + AddAssign + SubAssign - + for<'a> MulAssign<&'a Self> + + MulAssign + for<'a> AddAssign<&'a Self> + for<'a> SubAssign<&'a Self> + + for<'a> MulAssign<&'a Self> { - /// Returns an element chosen uniformly at random using a user-provided RNG. - fn random(rng: impl RngCore) -> Self; + /// The zero element of the field, the additive identity. + const ZERO: Self; - /// Returns the zero element of the field, the additive identity. - fn zero() -> Self; + /// The one element of the field, the multiplicative identity. + const ONE: Self; - /// Returns the one element of the field, the multiplicative identity. - fn one() -> Self; + /// Returns an element chosen uniformly at random using a user-provided RNG. + fn random(rng: impl RngCore) -> Self; /// Returns true iff this element is zero. fn is_zero(&self) -> Choice { - self.ct_eq(&Self::zero()) + self.ct_eq(&Self::ZERO) } /// Returns true iff this element is zero. @@ -101,17 +110,73 @@ pub trait Field: /// failing if the element is zero. fn invert(&self) -> CtOption<Self>; + /// Computes: + /// + /// - $(\textsf{true}, \sqrt{\textsf{num}/\textsf{div}})$, if $\textsf{num}$ and + /// $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is a square in the + /// field; + /// - $(\textsf{true}, 0)$, if $\textsf{num}$ is zero; + /// - $(\textsf{false}, 0)$, if $\textsf{num}$ is nonzero and $\textsf{div}$ is zero; + /// - $(\textsf{false}, \sqrt{G_S \cdot \textsf{num}/\textsf{div}})$, if + /// $\textsf{num}$ and $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is + /// a nonsquare in the field; + /// + /// where $G_S$ is a non-square. + /// + /// # Warnings + /// + /// - The choice of root from `sqrt` is unspecified. + /// - The value of $G_S$ is unspecified, and cannot be assumed to have any specific + /// value in a generic context. + fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self); + + /// Equivalent to `Self::sqrt_ratio(self, one())`. + /// + /// The provided method is implemented in terms of [`Self::sqrt_ratio`]. + fn sqrt_alt(&self) -> (Choice, Self) { + Self::sqrt_ratio(self, &Self::ONE) + } + /// Returns the square root of the field element, if it is /// quadratic residue. - fn sqrt(&self) -> CtOption<Self>; + /// + /// The provided method is implemented in terms of [`Self::sqrt_ratio`]. + fn sqrt(&self) -> CtOption<Self> { + let (is_square, res) = Self::sqrt_ratio(self, &Self::ONE); + CtOption::new(res, is_square) + } + + /// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer + /// exponent. + /// + /// # Guarantees + /// + /// This operation is constant time with respect to `self`, for all exponents with the + /// same number of digits (`exp.as_ref().len()`). It is variable time with respect to + /// the number of digits in the exponent. + fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self { + let mut res = Self::ONE; + for e in exp.as_ref().iter().rev() { + for i in (0..64).rev() { + res = res.square(); + let mut tmp = res; + tmp *= self; + res.conditional_assign(&tmp, (((*e >> i) & 1) as u8).into()); + } + } + res + } - /// Exponentiates `self` by `exp`, where `exp` is a little-endian order - /// integer exponent. + /// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer + /// exponent. /// - /// **This operation is variable time with respect to the exponent.** If the - /// exponent is fixed, this operation is effectively constant time. + /// # Guarantees + /// + /// **This operation is variable time with respect to `self`, for all exponent.** If + /// the exponent is fixed, this operation is effectively constant time. However, for + /// stronger constant-time guarantees, [`Field::pow`] should be used. fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self { - let mut res = Self::one(); + let mut res = Self::ONE; for e in exp.as_ref().iter().rev() { for i in (0..64).rev() { res = res.square(); @@ -126,7 +191,7 @@ pub trait Field: } } -/// This represents an element of a prime field. +/// This represents an element of a non-binary prime field. pub trait PrimeField: Field + From<u64> { /// The prime field can be converted back and forth into this binary /// representation. @@ -144,10 +209,10 @@ pub trait PrimeField: Field + From<u64> { } if s == "0" { - return Some(Self::zero()); + return Some(Self::ZERO); } - let mut res = Self::zero(); + let mut res = Self::ZERO; let ten = Self::from(10); @@ -176,6 +241,26 @@ pub trait PrimeField: Field + From<u64> { Some(res) } + /// Obtains a field element congruent to the integer `v`. + /// + /// For fields where `Self::CAPACITY >= 128`, this is injective and will produce a + /// unique field element. + /// + /// For fields where `Self::CAPACITY < 128`, this is surjective; some field elements + /// will be produced by multiple values of `v`. + /// + /// If you want to deterministically sample a field element representing a value, use + /// [`FromUniformBytes`] instead. + fn from_u128(v: u128) -> Self { + let lower = v as u64; + let upper = (v >> 64) as u64; + let mut tmp = Self::from(upper); + for _ in 0..64 { + tmp = tmp.double(); + } + tmp + Self::from(lower) + } + /// Attempts to convert a byte representation of a field element into an element of /// this prime field, failing if the input is not canonical (is not smaller than the /// field's modulus). @@ -215,6 +300,12 @@ pub trait PrimeField: Field + From<u64> { !self.is_odd() } + /// Modulus of the field written as a string for debugging purposes. + /// + /// The encoding of the modulus is implementation-specific. Generic users of the + /// `PrimeField` trait should treat this string as opaque. + const MODULUS: &'static str; + /// How many bits are needed to represent an element of this field. const NUM_BITS: u32; @@ -223,16 +314,19 @@ pub trait PrimeField: Field + From<u64> { /// This is usually `Self::NUM_BITS - 1`. const CAPACITY: u32; - /// Returns a fixed multiplicative generator of `modulus - 1` order. This element must - /// also be a quadratic nonresidue. + /// Inverse of $2$ in the field. + const TWO_INV: Self; + + /// A fixed multiplicative generator of `modulus - 1` order. This element must also be + /// a quadratic nonresidue. /// /// It can be calculated using [SageMath] as `GF(modulus).primitive_element()`. /// - /// Implementations of this method MUST ensure that this is the generator used to - /// derive `Self::root_of_unity`. + /// Implementations of this trait MUST ensure that this is the generator used to + /// derive `Self::ROOT_OF_UNITY`. /// /// [SageMath]: https://www.sagemath.org/ - fn multiplicative_generator() -> Self; + const MULTIPLICATIVE_GENERATOR: Self; /// An integer `s` satisfying the equation `2^s * t = modulus - 1` with `t` odd. /// @@ -240,11 +334,117 @@ pub trait PrimeField: Field + From<u64> { /// `modulus - 1`. const S: u32; - /// Returns the `2^s` root of unity. + /// The `2^s` root of unity. /// - /// It can be calculated by exponentiating `Self::multiplicative_generator` by `t`, + /// It can be calculated by exponentiating `Self::MULTIPLICATIVE_GENERATOR` by `t`, /// where `t = (modulus - 1) >> Self::S`. - fn root_of_unity() -> Self; + const ROOT_OF_UNITY: Self; + + /// Inverse of [`Self::ROOT_OF_UNITY`]. + const ROOT_OF_UNITY_INV: Self; + + /// Generator of the `t-order` multiplicative subgroup. + /// + /// It can be calculated by exponentiating [`Self::MULTIPLICATIVE_GENERATOR`] by `2^s`, + /// where `s` is [`Self::S`]. + const DELTA: Self; +} + +/// The subset of prime-order fields such that `(modulus - 1)` is divisible by `N`. +/// +/// If `N` is prime, there will be `N - 1` valid choices of [`Self::ZETA`]. Similarly to +/// [`PrimeField::MULTIPLICATIVE_GENERATOR`], the specific choice does not matter, as long +/// as the choice is consistent across all uses of the field. +pub trait WithSmallOrderMulGroup<const N: u8>: PrimeField { + /// A field element of small multiplicative order $N$. + /// + /// The presense of this element allows you to perform (certain types of) + /// endomorphisms on some elliptic curves. + /// + /// It can be calculated using [SageMath] as + /// `GF(modulus).primitive_element() ^ ((modulus - 1) // N)`. + /// Choosing the element of order $N$ that is smallest, when considered + /// as an integer, may help to ensure consistency. + /// + /// [SageMath]: https://www.sagemath.org/ + const ZETA: Self; +} + +/// Trait for constructing a [`PrimeField`] element from a fixed-length uniform byte +/// array. +/// +/// "Uniform" means that the byte array's contents must be indistinguishable from the +/// [discrete uniform distribution]. Suitable byte arrays can be obtained: +/// - from a cryptographically-secure randomness source (which makes this constructor +/// equivalent to [`Field::random`]). +/// - from a cryptographic hash function output, which enables a "random" field element to +/// be selected deterministically. This is the primary use case for `FromUniformBytes`. +/// +/// The length `N` of the byte array is chosen by the trait implementer such that the loss +/// of uniformity in the mapping from byte arrays to field elements is cryptographically +/// negligible. +/// +/// [discrete uniform distribution]: https://en.wikipedia.org/wiki/Discrete_uniform_distribution +/// +/// # Examples +/// +/// ``` +/// # #[cfg(feature = "derive")] { +/// # // Fake this so we don't actually need a dev-dependency on bls12_381. +/// # mod bls12_381 { +/// # use ff::{Field, PrimeField}; +/// # +/// # #[derive(PrimeField)] +/// # #[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] +/// # #[PrimeFieldGenerator = "7"] +/// # #[PrimeFieldReprEndianness = "little"] +/// # pub struct Scalar([u64; 4]); +/// # +/// # impl ff::FromUniformBytes<64> for Scalar { +/// # fn from_uniform_bytes(_bytes: &[u8; 64]) -> Self { +/// # // Fake impl for doctest +/// # Scalar::ONE +/// # } +/// # } +/// # } +/// # +/// use blake2b_simd::blake2b; +/// use bls12_381::Scalar; +/// use ff::FromUniformBytes; +/// +/// // `bls12_381::Scalar` implements `FromUniformBytes<64>`, and BLAKE2b (by default) +/// // produces a 64-byte hash. +/// let hash = blake2b(b"Some message"); +/// let val = Scalar::from_uniform_bytes(hash.as_array()); +/// # } +/// ``` +/// +/// # Implementing `FromUniformBytes` +/// +/// [`Self::from_uniform_bytes`] should always be implemented by interpreting the provided +/// byte array as the little endian unsigned encoding of an integer, and then reducing that +/// integer modulo the field modulus. +/// +/// For security, `N` must be chosen so that `N * 8 >= Self::NUM_BITS + 128`. A larger +/// value of `N` may be chosen for convenience; for example, for a field with a 255-bit +/// modulus, `N = 64` is convenient as it matches the output length of several common +/// cryptographic hash functions (such as SHA-512 and BLAKE2b). +/// +/// ## Trait design +/// +/// This trait exists because `PrimeField::from_uniform_bytes([u8; N])` cannot currently +/// exist (trait methods cannot use associated constants in the const positions of their +/// type signature, and we do not want `PrimeField` to require a generic const parameter). +/// However, this has the side-effect that `FromUniformBytes` can be implemented multiple +/// times for different values of `N`. Most implementations of [`PrimeField`] should only +/// need to implement `FromUniformBytes` trait for one value of `N` (chosen following the +/// above considerations); if you find yourself needing to implement it multiple times, +/// please [let us know about your use case](https://github.com/zkcrypto/ff/issues/new) so +/// we can take it into consideration for future evolutions of the `ff` traits. +pub trait FromUniformBytes<const N: usize>: PrimeField { + /// Returns a field element that is congruent to the provided little endian unsigned + /// byte representation of an integer. + fn from_uniform_bytes(bytes: &[u8; N]) -> Self; } /// This represents the bits of an element of a prime field. |