halo2curves_axiom/secp256k1/
fq.rs

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