halo2curves_axiom/secp256r1/
fq.rs

1use crate::arithmetic::{adc, bigint_geq, mac, macx, sbb};
2use crate::extend_field_legendre;
3use crate::ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup};
4use core::fmt;
5use core::ops::{Add, Mul, Neg, Sub};
6use rand::RngCore;
7use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
8
9/// This represents an element of $\mathbb{F}_q$ where
10///
11/// `q = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551`
12///
13/// is the scalar field of the secp256r1 curve.
14// The internal representation of this type is four 64-bit unsigned
15// integers in little-endian order. `Fq` values are always in
16// Montgomery form; i.e., Fq(a) = aR mod q, with R = 2^256.
17#[derive(Clone, Copy, PartialEq, Eq, Hash)]
18pub struct Fq(pub(crate) [u64; 4]);
19
20#[cfg(feature = "derive_serde")]
21crate::serialize_deserialize_32_byte_primefield!(Fq);
22
23/// Constant representing the modulus
24/// q = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
25const MODULUS: Fq = Fq([
26    0xf3b9cac2fc632551,
27    0xbce6faada7179e84,
28    0xffffffffffffffff,
29    0xffffffff00000000,
30]);
31
32/// The modulus as u32 limbs.
33#[cfg(not(target_pointer_width = "64"))]
34const MODULUS_LIMBS_32: [u32; 8] = [
35    0xfc63_2551,
36    0xf3b9_cac2,
37    0xa717_9e84,
38    0xbce6_faad,
39    0xffff_ffff,
40    0xffff_ffff,
41    0x0000_0000,
42    0xffff_ffff,
43];
44
45///Constant representing the modulus as static str
46const MODULUS_STR: &str = "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551";
47
48/// INV = -(q^{-1} mod 2^64) mod 2^64
49const INV: u64 = 0xccd1c8aaee00bc4f;
50
51/// R = 2^256 mod q
52/// 0xffffffff00000000000000004319055258e8617b0c46353d039cdaaf
53const R: Fq = Fq([
54    0x0c46353d039cdaaf,
55    0x4319055258e8617b,
56    0x0000000000000000,
57    0xffffffff,
58]);
59
60/// R^2 = 2^512 mod q
61/// 0x66e12d94f3d956202845b2392b6bec594699799c49bd6fa683244c95be79eea2
62const R2: Fq = Fq([
63    0x83244c95be79eea2,
64    0x4699799c49bd6fa6,
65    0x2845b2392b6bec59,
66    0x66e12d94f3d95620,
67]);
68
69/// R^3 = 2^768 mod q
70/// 0x503a54e76407be652543b9246ba5e93f111f28ae0c0555c9ac8ebec90b65a624
71const R3: Fq = Fq([
72    0xac8ebec90b65a624,
73    0x111f28ae0c0555c9,
74    0x2543b9246ba5e93f,
75    0x503a54e76407be65,
76]);
77
78/// `GENERATOR = 7 mod r` is a generator of the `q - 1` order multiplicative
79/// subgroup, or in other words a primitive root of the field.
80/// It's derived with SageMath with: `GF(MODULUS).primitive_element()`.
81const GENERATOR: Fq = Fq::from_raw([0x07, 0x00, 0x00, 0x00]);
82
83/// GENERATOR^t where t * 2^s + 1 = r with t odd. In other words, this is a 2^s root of unity.
84/// `ffc97f062a770992ba807ace842a3dfc1546cad004378daf0592d7fbb41e6602`
85const ROOT_OF_UNITY: Fq = Fq::from_raw([
86    0x0592d7fbb41e6602,
87    0x1546cad004378daf,
88    0xba807ace842a3dfc,
89    0xffc97f062a770992,
90]);
91
92/// 1 / ROOT_OF_UNITY mod q
93/// `a0a66a5562d46f2ac645fa0458131caee3ac117c794c4137379c7f0657c73764`
94const ROOT_OF_UNITY_INV: Fq = Fq::from_raw([
95    0x379c7f0657c73764,
96    0xe3ac117c794c4137,
97    0xc645fa0458131cae,
98    0xa0a66a5562d46f2a,
99]);
100
101/// 1 / 2 mod q
102const TWO_INV: Fq = Fq::from_raw([
103    0x79dce5617e3192a9,
104    0xde737d56d38bcf42,
105    0x7fffffffffffffff,
106    0x7fffffff80000000,
107]);
108
109const ZETA: Fq = Fq::from_raw([
110    0x7cbf87ff12884e21,
111    0x9405335ce9c83e1d,
112    0x4e786d0777fd6aef,
113    0x52891d43d946a035,
114]);
115
116/// Generator of the t-order multiplicative subgroup.
117/// Computed by exponentiating Self::MULTIPLICATIVE_GENERATOR by 2^s, where s is Self::S.
118const DELTA: Fq = Fq::from_raw([0x1e39a5057d81, 0, 0, 0]);
119
120use crate::{
121    field_arithmetic, field_common, field_specific, impl_add_binop_specify_output,
122    impl_binops_additive, impl_binops_additive_specify_output, impl_binops_multiplicative,
123    impl_binops_multiplicative_mixed, impl_from_u64, impl_sub_binop_specify_output, impl_sum_prod,
124};
125impl_binops_additive!(Fq, Fq);
126impl_binops_multiplicative!(Fq, Fq);
127field_common!(
128    Fq,
129    MODULUS,
130    INV,
131    MODULUS_STR,
132    TWO_INV,
133    ROOT_OF_UNITY_INV,
134    DELTA,
135    ZETA,
136    R,
137    R2,
138    R3
139);
140impl_from_u64!(Fq, R2);
141field_arithmetic!(Fq, MODULUS, INV, dense);
142impl_sum_prod!(Fq);
143
144impl Fq {
145    pub const fn size() -> usize {
146        32
147    }
148}
149
150impl ff::Field for Fq {
151    const ZERO: Self = Self::zero();
152    const ONE: Self = Self::one();
153
154    fn random(mut rng: impl RngCore) -> Self {
155        Self::from_u512([
156            rng.next_u64(),
157            rng.next_u64(),
158            rng.next_u64(),
159            rng.next_u64(),
160            rng.next_u64(),
161            rng.next_u64(),
162            rng.next_u64(),
163            rng.next_u64(),
164        ])
165    }
166
167    fn double(&self) -> Self {
168        self.double()
169    }
170
171    #[inline(always)]
172    fn square(&self) -> Self {
173        self.square()
174    }
175
176    /// Returns the multiplicative inverse of the
177    /// element. If it is zero, the method fails.
178    fn invert(&self) -> CtOption<Self> {
179        self.invert()
180    }
181
182    fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
183        let mut res = Self::one();
184        let mut found_one = false;
185        for e in exp.as_ref().iter().rev() {
186            for i in (0..64).rev() {
187                if found_one {
188                    res = res.square();
189                }
190
191                if ((*e >> i) & 1) == 1 {
192                    found_one = true;
193                    res *= self;
194                }
195            }
196        }
197        res
198    }
199
200    fn sqrt(&self) -> CtOption<Self> {
201        // 7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a
202        let tm1d2 = [
203            0x279dce5617e3192a,
204            0xfde737d56d38bcf4,
205            0x07ffffffffffffff,
206            0x7fffffff8000000,
207        ];
208
209        ff::helpers::sqrt_tonelli_shanks(self, tm1d2)
210    }
211
212    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
213        ff::helpers::sqrt_ratio_generic(num, div)
214    }
215}
216
217impl ff::PrimeField for Fq {
218    type Repr = [u8; 32];
219
220    const NUM_BITS: u32 = 256;
221    const CAPACITY: u32 = 255;
222    const MODULUS: &'static str = MODULUS_STR;
223    const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;
224    const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
225    const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV;
226    const TWO_INV: Self = TWO_INV;
227    const DELTA: Self = DELTA;
228    const S: u32 = 4;
229
230    fn from_repr(repr: Self::Repr) -> CtOption<Self> {
231        let mut tmp = Fq([0, 0, 0, 0]);
232
233        tmp.0[0] = u64::from_le_bytes(repr[0..8].try_into().unwrap());
234        tmp.0[1] = u64::from_le_bytes(repr[8..16].try_into().unwrap());
235        tmp.0[2] = u64::from_le_bytes(repr[16..24].try_into().unwrap());
236        tmp.0[3] = u64::from_le_bytes(repr[24..32].try_into().unwrap());
237
238        // Try to subtract the modulus
239        let (_, borrow) = sbb(tmp.0[0], MODULUS.0[0], 0);
240        let (_, borrow) = sbb(tmp.0[1], MODULUS.0[1], borrow);
241        let (_, borrow) = sbb(tmp.0[2], MODULUS.0[2], borrow);
242        let (_, borrow) = sbb(tmp.0[3], MODULUS.0[3], borrow);
243
244        // If the element is smaller than MODULUS then the
245        // subtraction will underflow, producing a borrow value
246        // of 0xffff...ffff. Otherwise, it'll be zero.
247        let is_some = (borrow as u8) & 1;
248
249        // Convert to Montgomery form by computi
250        // (a.R^0 * R^2) / R = a.R
251        tmp *= &R2;
252
253        CtOption::new(tmp, Choice::from(is_some))
254    }
255
256    fn to_repr(&self) -> Self::Repr {
257        let tmp: [u64; 4] = (*self).into();
258        let mut res = [0; 32];
259        res[0..8].copy_from_slice(&tmp[0].to_le_bytes());
260        res[8..16].copy_from_slice(&tmp[1].to_le_bytes());
261        res[16..24].copy_from_slice(&tmp[2].to_le_bytes());
262        res[24..32].copy_from_slice(&tmp[3].to_le_bytes());
263
264        res
265    }
266
267    fn is_odd(&self) -> Choice {
268        Choice::from(self.to_repr()[0] & 1)
269    }
270}
271
272impl FromUniformBytes<64> for Fq {
273    /// Converts a 512-bit little endian integer into
274    /// an `Fq` by reducing by the modulus.
275    fn from_uniform_bytes(bytes: &[u8; 64]) -> Self {
276        Self::from_u512([
277            u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
278            u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
279            u64::from_le_bytes(bytes[16..24].try_into().unwrap()),
280            u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
281            u64::from_le_bytes(bytes[32..40].try_into().unwrap()),
282            u64::from_le_bytes(bytes[40..48].try_into().unwrap()),
283            u64::from_le_bytes(bytes[48..56].try_into().unwrap()),
284            u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
285        ])
286    }
287}
288
289impl WithSmallOrderMulGroup<3> for Fq {
290    const ZETA: Self = ZETA;
291}
292
293extend_field_legendre!(Fq);
294
295#[cfg(test)]
296mod test {
297    use super::*;
298    use ff::Field;
299    use rand_core::OsRng;
300
301    #[test]
302    fn test_zeta() {
303        assert_eq!(Fq::ZETA * Fq::ZETA * Fq::ZETA, Fq::ONE);
304        assert_ne!(Fq::ZETA * Fq::ZETA, Fq::ONE);
305    }
306
307    #[test]
308    fn test_sqrt() {
309        // NB: TWO_INV is standing in as a "random" field element
310        // let v = (Fq::TWO_INV).square().sqrt().unwrap();
311        // assert!(v == Fq::TWO_INV || (-v) == Fq::TWO_INV);
312
313        for _ in 0..10000 {
314            let a = Fq::random(OsRng);
315            let mut b = a;
316            b = b.square();
317
318            let b = b.sqrt().unwrap();
319            let mut negb = b;
320            negb = negb.neg();
321
322            assert!(a == b || a == negb);
323        }
324    }
325
326    #[test]
327    fn test_constants() {
328        assert_eq!(
329            Fq::MODULUS,
330            "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
331        );
332
333        assert_eq!(Fq::from(2) * Fq::TWO_INV, Fq::ONE);
334    }
335
336    #[test]
337    fn test_delta() {
338        assert_eq!(Fq::DELTA, Fq::MULTIPLICATIVE_GENERATOR.pow([1u64 << Fq::S]));
339    }
340
341    #[test]
342    fn test_root_of_unity() {
343        assert_eq!(Fq::ROOT_OF_UNITY.pow_vartime([1 << Fq::S]), Fq::one());
344    }
345
346    #[test]
347    fn test_inv_root_of_unity() {
348        assert_eq!(Fq::ROOT_OF_UNITY_INV, Fq::ROOT_OF_UNITY.invert().unwrap());
349    }
350
351    #[test]
352    fn test_field() {
353        crate::tests::field::random_field_tests::<Fq>("secp256r1 scalar".to_string());
354    }
355
356    #[test]
357    fn test_conversion() {
358        crate::tests::field::random_conversion_tests::<Fq>("secp256r1 scalar".to_string());
359    }
360
361    #[test]
362    fn test_serialization() {
363        crate::tests::field::random_serialization_test::<Fq>("secp256r1 scalar".to_string());
364        #[cfg(feature = "derive_serde")]
365        crate::tests::field::random_serde_test::<Fq>("secp256r1 scalar".to_string());
366    }
367
368    #[test]
369    fn test_quadratic_residue() {
370        crate::tests::field::random_quadratic_residue_test::<Fq>();
371    }
372}