dcrypt_algorithms/ec/bls12_381/
scalar.rs

1//! BLS12-381 scalar field F_q where q = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
2
3use crate::error::{Error, Result};
4use crate::types::{
5    ByteSerializable, ConstantTimeEq as DcryptConstantTimeEq, SecureZeroingType,
6};
7use core::fmt;
8use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
9use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
10
11// Arithmetic helpers
12/// Compute a + b + carry, returning (result, carry)
13#[inline(always)]
14const fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) {
15    let ret = (a as u128) + (b as u128) + (carry as u128);
16    (ret as u64, (ret >> 64) as u64)
17}
18
19/// Compute a - (b + borrow), returning (result, borrow)
20#[inline(always)]
21const fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) {
22    let ret = (a as u128).wrapping_sub((b as u128) + ((borrow >> 63) as u128));
23    (ret as u64, (ret >> 64) as u64)
24}
25
26/// Compute a + (b * c) + carry, returning (result, carry)
27#[inline(always)]
28const fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) {
29    let ret = (a as u128) + ((b as u128) * (c as u128)) + (carry as u128);
30    (ret as u64, (ret >> 64) as u64)
31}
32
33/// Scalar field element of BLS12-381
34/// Internal: Four 64-bit limbs in little-endian Montgomery form
35#[derive(Clone, Copy, Eq)]
36pub struct Scalar(pub(crate) [u64; 4]);
37
38impl fmt::Debug for Scalar {
39    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40        let tmp = self.to_bytes();
41        write!(f, "0x")?;
42        for &b in tmp.iter().rev() {
43            write!(f, "{:02x}", b)?;
44        }
45        Ok(())
46    }
47}
48
49impl fmt::Display for Scalar {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        write!(f, "{:?}", self)
52    }
53}
54
55impl From<u64> for Scalar {
56    fn from(val: u64) -> Scalar {
57        Scalar([val, 0, 0, 0]) * R2
58    }
59}
60
61impl ConstantTimeEq for Scalar {
62    fn ct_eq(&self, other: &Self) -> Choice {
63        self.0[0].ct_eq(&other.0[0])
64            & self.0[1].ct_eq(&other.0[1])
65            & self.0[2].ct_eq(&other.0[2])
66            & self.0[3].ct_eq(&other.0[3])
67    }
68}
69
70impl PartialEq for Scalar {
71    #[inline]
72    fn eq(&self, other: &Self) -> bool {
73        bool::from(subtle::ConstantTimeEq::ct_eq(self, other))
74    }
75}
76
77impl ConditionallySelectable for Scalar {
78    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
79        Scalar([
80            u64::conditional_select(&a.0[0], &b.0[0], choice),
81            u64::conditional_select(&a.0[1], &b.0[1], choice),
82            u64::conditional_select(&a.0[2], &b.0[2], choice),
83            u64::conditional_select(&a.0[3], &b.0[3], choice),
84        ])
85    }
86}
87
88// Constants
89const MODULUS: Scalar = Scalar([
90    0xffff_ffff_0000_0001,
91    0x53bd_a402_fffe_5bfe,
92    0x3339_d808_09a1_d805,
93    0x73ed_a753_299d_7d48,
94]);
95
96/// INV = -(q^{-1} mod 2^64) mod 2^64
97const INV: u64 = 0xffff_fffe_ffff_ffff;
98
99/// R = 2^256 mod q
100const R: Scalar = Scalar([
101    0x0000_0001_ffff_fffe,
102    0x5884_b7fa_0003_4802,
103    0x998c_4fef_ecbc_4ff5,
104    0x1824_b159_acc5_056f,
105]);
106
107/// R^2 = 2^512 mod q
108const R2: Scalar = Scalar([
109    0xc999_e990_f3f2_9c6d,
110    0x2b6c_edcb_8792_5c23,
111    0x05d3_1496_7254_398f,
112    0x0748_d9d9_9f59_ff11,
113]);
114
115/// R^3 = 2^768 mod q
116const R3: Scalar = Scalar([
117    0xc62c_1807_439b_73af,
118    0x1b3e_0d18_8cf0_6990,
119    0x73d1_3c71_c7b5_f418,
120    0x6e2a_5bb9_c8db_33e9,
121]);
122
123impl<'a> Neg for &'a Scalar {
124    type Output = Scalar;
125
126    #[inline]
127    fn neg(self) -> Scalar {
128        self.neg()
129    }
130}
131
132impl Neg for Scalar {
133    type Output = Scalar;
134
135    #[inline]
136    fn neg(self) -> Scalar {
137        -&self
138    }
139}
140
141impl<'a, 'b> Sub<&'b Scalar> for &'a Scalar {
142    type Output = Scalar;
143
144    #[inline]
145    fn sub(self, rhs: &'b Scalar) -> Scalar {
146        self.sub(rhs)
147    }
148}
149
150impl<'a, 'b> Add<&'b Scalar> for &'a Scalar {
151    type Output = Scalar;
152
153    #[inline]
154    fn add(self, rhs: &'b Scalar) -> Scalar {
155        self.add(rhs)
156    }
157}
158
159impl<'a, 'b> Mul<&'b Scalar> for &'a Scalar {
160    type Output = Scalar;
161
162    #[inline]
163    fn mul(self, rhs: &'b Scalar) -> Scalar {
164        self.mul(rhs)
165    }
166}
167
168// Binop implementations
169impl<'b> Add<&'b Scalar> for Scalar {
170    type Output = Scalar;
171    #[inline]
172    fn add(self, rhs: &'b Scalar) -> Scalar {
173        &self + rhs
174    }
175}
176
177impl<'a> Add<Scalar> for &'a Scalar {
178    type Output = Scalar;
179    #[inline]
180    fn add(self, rhs: Scalar) -> Scalar {
181        self + &rhs
182    }
183}
184
185impl Add<Scalar> for Scalar {
186    type Output = Scalar;
187    #[inline]
188    fn add(self, rhs: Scalar) -> Scalar {
189        &self + &rhs
190    }
191}
192
193impl<'b> Sub<&'b Scalar> for Scalar {
194    type Output = Scalar;
195    #[inline]
196    fn sub(self, rhs: &'b Scalar) -> Scalar {
197        &self - rhs
198    }
199}
200
201impl<'a> Sub<Scalar> for &'a Scalar {
202    type Output = Scalar;
203    #[inline]
204    fn sub(self, rhs: Scalar) -> Scalar {
205        self - &rhs
206    }
207}
208
209impl Sub<Scalar> for Scalar {
210    type Output = Scalar;
211    #[inline]
212    fn sub(self, rhs: Scalar) -> Scalar {
213        &self - &rhs
214    }
215}
216
217impl SubAssign<Scalar> for Scalar {
218    #[inline]
219    fn sub_assign(&mut self, rhs: Scalar) {
220        *self = &*self - &rhs;
221    }
222}
223
224impl AddAssign<Scalar> for Scalar {
225    #[inline]
226    fn add_assign(&mut self, rhs: Scalar) {
227        *self = &*self + &rhs;
228    }
229}
230
231impl<'b> SubAssign<&'b Scalar> for Scalar {
232    #[inline]
233    fn sub_assign(&mut self, rhs: &'b Scalar) {
234        *self = &*self - rhs;
235    }
236}
237
238impl<'b> AddAssign<&'b Scalar> for Scalar {
239    #[inline]
240    fn add_assign(&mut self, rhs: &'b Scalar) {
241        *self = &*self + rhs;
242    }
243}
244
245impl<'b> Mul<&'b Scalar> for Scalar {
246    type Output = Scalar;
247    #[inline]
248    fn mul(self, rhs: &'b Scalar) -> Scalar {
249        &self * rhs
250    }
251}
252
253impl<'a> Mul<Scalar> for &'a Scalar {
254    type Output = Scalar;
255    #[inline]
256    fn mul(self, rhs: Scalar) -> Scalar {
257        self * &rhs
258    }
259}
260
261impl Mul<Scalar> for Scalar {
262    type Output = Scalar;
263    #[inline]
264    fn mul(self, rhs: Scalar) -> Scalar {
265        &self * &rhs
266    }
267}
268
269impl MulAssign<Scalar> for Scalar {
270    #[inline]
271    fn mul_assign(&mut self, rhs: Scalar) {
272        *self = &*self * &rhs;
273    }
274}
275
276impl<'b> MulAssign<&'b Scalar> for Scalar {
277    #[inline]
278    fn mul_assign(&mut self, rhs: &'b Scalar) {
279        *self = &*self * rhs;
280    }
281}
282
283impl Default for Scalar {
284    #[inline]
285    fn default() -> Self {
286        Self::zero()
287    }
288}
289
290#[cfg(feature = "zeroize")]
291impl zeroize::DefaultIsZeroes for Scalar {}
292impl ByteSerializable for Scalar {
293    fn to_bytes(&self) -> Vec<u8> {
294        self.to_bytes().to_vec()
295    }
296
297    fn from_bytes(bytes: &[u8]) -> Result<Self> {
298        if bytes.len() != 32 {
299            return Err(Error::Length {
300                context: "Scalar::from_bytes",
301                expected: 32,
302                actual: bytes.len(),
303            });
304        }
305
306        let mut array = [0u8; 32];
307        array.copy_from_slice(bytes);
308
309        Scalar::from_bytes(&array)
310            .into_option()  // Use into_option() instead of into()
311            .ok_or_else(|| Error::param("scalar_bytes", "non-canonical scalar"))
312    }
313}
314
315impl DcryptConstantTimeEq for Scalar {
316    fn ct_eq(&self, other: &Self) -> bool {
317        bool::from(subtle::ConstantTimeEq::ct_eq(self, other))
318    }
319}
320
321impl SecureZeroingType for Scalar {
322    fn zeroed() -> Self {
323        Self::zero()
324    }
325}
326
327impl Scalar {
328    /// Additive identity
329    #[inline]
330    pub const fn zero() -> Scalar {
331        Scalar([0, 0, 0, 0])
332    }
333
334    /// Multiplicative identity
335    #[inline]
336    pub const fn one() -> Scalar {
337        R
338    }
339
340    /// Double this element
341    #[inline]
342    pub const fn double(&self) -> Scalar {
343        self.add(self)
344    }
345
346    /// Create from little-endian bytes if canonical
347    pub fn from_bytes(bytes: &[u8; 32]) -> CtOption<Scalar> {
348        let mut tmp = Scalar([0, 0, 0, 0]);
349
350        tmp.0[0] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[0..8]).unwrap());
351        tmp.0[1] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap());
352        tmp.0[2] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[16..24]).unwrap());
353        tmp.0[3] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[24..32]).unwrap());
354
355        // Check canonical by subtracting modulus
356        let (_, borrow) = sbb(tmp.0[0], MODULUS.0[0], 0);
357        let (_, borrow) = sbb(tmp.0[1], MODULUS.0[1], borrow);
358        let (_, borrow) = sbb(tmp.0[2], MODULUS.0[2], borrow);
359        let (_, borrow) = sbb(tmp.0[3], MODULUS.0[3], borrow);
360
361        let is_some = (borrow as u8) & 1;
362
363        // Convert to Montgomery: (a * R^2) / R = aR
364        tmp *= &R2;
365
366        CtOption::new(tmp, Choice::from(is_some))
367    }
368
369    /// Convert to little-endian bytes
370    pub fn to_bytes(&self) -> [u8; 32] {
371        // Remove Montgomery: (aR) / R = a
372        let tmp = Scalar::montgomery_reduce(self.0[0], self.0[1], self.0[2], self.0[3], 0, 0, 0, 0);
373
374        let mut res = [0; 32];
375        res[0..8].copy_from_slice(&tmp.0[0].to_le_bytes());
376        res[8..16].copy_from_slice(&tmp.0[1].to_le_bytes());
377        res[16..24].copy_from_slice(&tmp.0[2].to_le_bytes());
378        res[24..32].copy_from_slice(&tmp.0[3].to_le_bytes());
379
380        res
381    }
382
383    /// Create from 512-bit little-endian integer mod q
384    pub fn from_bytes_wide(bytes: &[u8; 64]) -> Scalar {
385        Scalar::from_u512([
386            u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[0..8]).unwrap()),
387            u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap()),
388            u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[16..24]).unwrap()),
389            u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[24..32]).unwrap()),
390            u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[32..40]).unwrap()),
391            u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[40..48]).unwrap()),
392            u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[48..56]).unwrap()),
393            u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[56..64]).unwrap()),
394        ])
395    }
396
397    fn from_u512(limbs: [u64; 8]) -> Scalar {
398        let d0 = Scalar([limbs[0], limbs[1], limbs[2], limbs[3]]);
399        let d1 = Scalar([limbs[4], limbs[5], limbs[6], limbs[7]]);
400        d0 * R2 + d1 * R3
401    }
402
403    /// Create from raw values and convert to Montgomery
404    pub const fn from_raw(val: [u64; 4]) -> Self {
405        (&Scalar(val)).mul(&R2)
406    }
407
408    /// Square this element
409    #[inline]
410    pub const fn square(&self) -> Scalar {
411        let (r1, carry) = mac(0, self.0[0], self.0[1], 0);
412        let (r2, carry) = mac(0, self.0[0], self.0[2], carry);
413        let (r3, r4) = mac(0, self.0[0], self.0[3], carry);
414
415        let (r3, carry) = mac(r3, self.0[1], self.0[2], 0);
416        let (r4, r5) = mac(r4, self.0[1], self.0[3], carry);
417
418        let (r5, r6) = mac(r5, self.0[2], self.0[3], 0);
419
420        let r7 = r6 >> 63;
421        let r6 = (r6 << 1) | (r5 >> 63);
422        let r5 = (r5 << 1) | (r4 >> 63);
423        let r4 = (r4 << 1) | (r3 >> 63);
424        let r3 = (r3 << 1) | (r2 >> 63);
425        let r2 = (r2 << 1) | (r1 >> 63);
426        let r1 = r1 << 1;
427
428        let (r0, carry) = mac(0, self.0[0], self.0[0], 0);
429        let (r1, carry) = adc(0, r1, carry);
430        let (r2, carry) = mac(r2, self.0[1], self.0[1], carry);
431        let (r3, carry) = adc(0, r3, carry);
432        let (r4, carry) = mac(r4, self.0[2], self.0[2], carry);
433        let (r5, carry) = adc(0, r5, carry);
434        let (r6, carry) = mac(r6, self.0[3], self.0[3], carry);
435        let (r7, _) = adc(0, r7, carry);
436
437        Scalar::montgomery_reduce(r0, r1, r2, r3, r4, r5, r6, r7)
438    }
439
440    /// Multiplicative inverse
441    pub fn invert(&self) -> CtOption<Self> {
442        #[inline(always)]
443        fn square_assign_multi(n: &mut Scalar, num_times: usize) {
444            for _ in 0..num_times {
445                *n = n.square();
446            }
447        }
448        // Addition chain from github.com/kwantam/addchain
449        let mut t0 = self.square();
450        let mut t1 = t0 * self;
451        let mut t16 = t0.square();
452        let mut t6 = t16.square();
453        let mut t5 = t6 * t0;
454        t0 = t6 * t16;
455        let mut t12 = t5 * t16;
456        let mut t2 = t6.square();
457        let mut t7 = t5 * t6;
458        let mut t15 = t0 * t5;
459        let mut t17 = t12.square();
460        t1 *= t17;
461        let mut t3 = t7 * t2;
462        let t8 = t1 * t17;
463        let t4 = t8 * t2;
464        let t9 = t8 * t7;
465        t7 = t4 * t5;
466        let t11 = t4 * t17;
467        t5 = t9 * t17;
468        let t14 = t7 * t15;
469        let t13 = t11 * t12;
470        t12 = t11 * t17;
471        t15 *= &t12;
472        t16 *= &t15;
473        t3 *= &t16;
474        t17 *= &t3;
475        t0 *= &t17;
476        t6 *= &t0;
477        t2 *= &t6;
478        square_assign_multi(&mut t0, 8);
479        t0 *= &t17;
480        square_assign_multi(&mut t0, 9);
481        t0 *= &t16;
482        square_assign_multi(&mut t0, 9);
483        t0 *= &t15;
484        square_assign_multi(&mut t0, 9);
485        t0 *= &t15;
486        square_assign_multi(&mut t0, 7);
487        t0 *= &t14;
488        square_assign_multi(&mut t0, 7);
489        t0 *= &t13;
490        square_assign_multi(&mut t0, 10);
491        t0 *= &t12;
492        square_assign_multi(&mut t0, 9);
493        t0 *= &t11;
494        square_assign_multi(&mut t0, 8);
495        t0 *= &t8;
496        square_assign_multi(&mut t0, 8);
497        t0 *= self;
498        square_assign_multi(&mut t0, 14);
499        t0 *= &t9;
500        square_assign_multi(&mut t0, 10);
501        t0 *= &t8;
502        square_assign_multi(&mut t0, 15);
503        t0 *= &t7;
504        square_assign_multi(&mut t0, 10);
505        t0 *= &t6;
506        square_assign_multi(&mut t0, 8);
507        t0 *= &t5;
508        square_assign_multi(&mut t0, 16);
509        t0 *= &t3;
510        square_assign_multi(&mut t0, 8);
511        t0 *= &t2;
512        square_assign_multi(&mut t0, 7);
513        t0 *= &t4;
514        square_assign_multi(&mut t0, 9);
515        t0 *= &t2;
516        square_assign_multi(&mut t0, 8);
517        t0 *= &t3;
518        square_assign_multi(&mut t0, 8);
519        t0 *= &t2;
520        square_assign_multi(&mut t0, 8);
521        t0 *= &t2;
522        square_assign_multi(&mut t0, 8);
523        t0 *= &t2;
524        square_assign_multi(&mut t0, 8);
525        t0 *= &t3;
526        square_assign_multi(&mut t0, 8);
527        t0 *= &t2;
528        square_assign_multi(&mut t0, 8);
529        t0 *= &t2;
530        square_assign_multi(&mut t0, 5);
531        t0 *= &t1;
532        square_assign_multi(&mut t0, 5);
533        t0 *= &t1;
534
535        CtOption::new(t0, !subtle::ConstantTimeEq::ct_eq(self, &Self::zero()))
536    }
537
538    #[inline(always)]
539    const fn montgomery_reduce(
540        r0: u64,
541        r1: u64,
542        r2: u64,
543        r3: u64,
544        r4: u64,
545        r5: u64,
546        r6: u64,
547        r7: u64,
548    ) -> Self {
549        let k = r0.wrapping_mul(INV);
550        let (_, carry) = mac(r0, k, MODULUS.0[0], 0);
551        let (r1, carry) = mac(r1, k, MODULUS.0[1], carry);
552        let (r2, carry) = mac(r2, k, MODULUS.0[2], carry);
553        let (r3, carry) = mac(r3, k, MODULUS.0[3], carry);
554        let (r4, carry2) = adc(r4, 0, carry);
555
556        let k = r1.wrapping_mul(INV);
557        let (_, carry) = mac(r1, k, MODULUS.0[0], 0);
558        let (r2, carry) = mac(r2, k, MODULUS.0[1], carry);
559        let (r3, carry) = mac(r3, k, MODULUS.0[2], carry);
560        let (r4, carry) = mac(r4, k, MODULUS.0[3], carry);
561        let (r5, carry2) = adc(r5, carry2, carry);
562
563        let k = r2.wrapping_mul(INV);
564        let (_, carry) = mac(r2, k, MODULUS.0[0], 0);
565        let (r3, carry) = mac(r3, k, MODULUS.0[1], carry);
566        let (r4, carry) = mac(r4, k, MODULUS.0[2], carry);
567        let (r5, carry) = mac(r5, k, MODULUS.0[3], carry);
568        let (r6, carry2) = adc(r6, carry2, carry);
569
570        let k = r3.wrapping_mul(INV);
571        let (_, carry) = mac(r3, k, MODULUS.0[0], 0);
572        let (r4, carry) = mac(r4, k, MODULUS.0[1], carry);
573        let (r5, carry) = mac(r5, k, MODULUS.0[2], carry);
574        let (r6, carry) = mac(r6, k, MODULUS.0[3], carry);
575        let (r7, _) = adc(r7, carry2, carry);
576
577        (&Scalar([r4, r5, r6, r7])).sub(&MODULUS)
578    }
579
580    /// Multiply two scalars
581    #[inline]
582    pub const fn mul(&self, rhs: &Self) -> Self {
583        let (r0, carry) = mac(0, self.0[0], rhs.0[0], 0);
584        let (r1, carry) = mac(0, self.0[0], rhs.0[1], carry);
585        let (r2, carry) = mac(0, self.0[0], rhs.0[2], carry);
586        let (r3, r4) = mac(0, self.0[0], rhs.0[3], carry);
587
588        let (r1, carry) = mac(r1, self.0[1], rhs.0[0], 0);
589        let (r2, carry) = mac(r2, self.0[1], rhs.0[1], carry);
590        let (r3, carry) = mac(r3, self.0[1], rhs.0[2], carry);
591        let (r4, r5) = mac(r4, self.0[1], rhs.0[3], carry);
592
593        let (r2, carry) = mac(r2, self.0[2], rhs.0[0], 0);
594        let (r3, carry) = mac(r3, self.0[2], rhs.0[1], carry);
595        let (r4, carry) = mac(r4, self.0[2], rhs.0[2], carry);
596        let (r5, r6) = mac(r5, self.0[2], rhs.0[3], carry);
597
598        let (r3, carry) = mac(r3, self.0[3], rhs.0[0], 0);
599        let (r4, carry) = mac(r4, self.0[3], rhs.0[1], carry);
600        let (r5, carry) = mac(r5, self.0[3], rhs.0[2], carry);
601        let (r6, r7) = mac(r6, self.0[3], rhs.0[3], carry);
602
603        Scalar::montgomery_reduce(r0, r1, r2, r3, r4, r5, r6, r7)
604    }
605
606    /// Subtract rhs from self
607    #[inline]
608    pub const fn sub(&self, rhs: &Self) -> Self {
609        let (d0, borrow) = sbb(self.0[0], rhs.0[0], 0);
610        let (d1, borrow) = sbb(self.0[1], rhs.0[1], borrow);
611        let (d2, borrow) = sbb(self.0[2], rhs.0[2], borrow);
612        let (d3, borrow) = sbb(self.0[3], rhs.0[3], borrow);
613
614        let (d0, carry) = adc(d0, MODULUS.0[0] & borrow, 0);
615        let (d1, carry) = adc(d1, MODULUS.0[1] & borrow, carry);
616        let (d2, carry) = adc(d2, MODULUS.0[2] & borrow, carry);
617        let (d3, _) = adc(d3, MODULUS.0[3] & borrow, carry);
618
619        Scalar([d0, d1, d2, d3])
620    }
621
622    /// Add rhs to self
623    #[inline]
624    pub const fn add(&self, rhs: &Self) -> Self {
625        let (d0, carry) = adc(self.0[0], rhs.0[0], 0);
626        let (d1, carry) = adc(self.0[1], rhs.0[1], carry);
627        let (d2, carry) = adc(self.0[2], rhs.0[2], carry);
628        let (d3, _) = adc(self.0[3], rhs.0[3], carry);
629
630        (&Scalar([d0, d1, d2, d3])).sub(&MODULUS)
631    }
632
633    /// Negate self
634    #[inline]
635    pub const fn neg(&self) -> Self {
636        let (d0, borrow) = sbb(MODULUS.0[0], self.0[0], 0);
637        let (d1, borrow) = sbb(MODULUS.0[1], self.0[1], borrow);
638        let (d2, borrow) = sbb(MODULUS.0[2], self.0[2], borrow);
639        let (d3, _) = sbb(MODULUS.0[3], self.0[3], borrow);
640
641        let mask = (((self.0[0] | self.0[1] | self.0[2] | self.0[3]) == 0) as u64).wrapping_sub(1);
642
643        Scalar([d0 & mask, d1 & mask, d2 & mask, d3 & mask])
644    }
645}
646
647impl From<Scalar> for [u8; 32] {
648    fn from(value: Scalar) -> [u8; 32] {
649        value.to_bytes()
650    }
651}
652
653impl<'a> From<&'a Scalar> for [u8; 32] {
654    fn from(value: &'a Scalar) -> [u8; 32] {
655        value.to_bytes()
656    }
657}
658
659impl<T> core::iter::Sum<T> for Scalar
660where
661    T: core::borrow::Borrow<Scalar>,
662{
663    fn sum<I>(iter: I) -> Self
664    where
665        I: Iterator<Item = T>,
666    {
667        iter.fold(Self::zero(), |acc, item| acc + item.borrow())
668    }
669}
670
671impl<T> core::iter::Product<T> for Scalar
672where
673    T: core::borrow::Borrow<Scalar>,
674{
675    fn product<I>(iter: I) -> Self
676    where
677        I: Iterator<Item = T>,
678    {
679        iter.fold(Self::one(), |acc, item| acc * item.borrow())
680    }
681}
682
683// Tests
684#[test]
685fn test_inv() {
686    // Verify INV constant
687    let mut inv = 1u64;
688    for _ in 0..63 {
689        inv = inv.wrapping_mul(inv);
690        inv = inv.wrapping_mul(MODULUS.0[0]);
691    }
692    inv = inv.wrapping_neg();
693    assert_eq!(inv, INV);
694}
695
696#[cfg(feature = "std")]
697#[test]
698fn test_debug() {
699    assert_eq!(
700        format!("{:?}", Scalar::zero()),
701        "0x0000000000000000000000000000000000000000000000000000000000000000"
702    );
703    assert_eq!(
704        format!("{:?}", Scalar::one()),
705        "0x0000000000000000000000000000000000000000000000000000000000000001"
706    );
707    assert_eq!(
708        format!("{:?}", R2),
709        "0x1824b159acc5056f998c4fefecbc4ff55884b7fa0003480200000001fffffffe"
710    );
711}
712
713#[test]
714fn test_equality() {
715    assert_eq!(Scalar::zero(), Scalar::zero());
716    assert_eq!(Scalar::one(), Scalar::one());
717    #[allow(clippy::eq_op)]
718    {
719        assert_eq!(R2, R2);
720    }
721
722    assert!(Scalar::zero() != Scalar::one());
723    assert!(Scalar::one() != R2);
724}
725
726#[test]
727fn test_to_bytes() {
728    assert_eq!(
729        Scalar::zero().to_bytes(),
730        [
731            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
732            0, 0, 0
733        ]
734    );
735
736    assert_eq!(
737        Scalar::one().to_bytes(),
738        [
739            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
740            0, 0, 0
741        ]
742    );
743
744    assert_eq!(
745        R2.to_bytes(),
746        [
747            254, 255, 255, 255, 1, 0, 0, 0, 2, 72, 3, 0, 250, 183, 132, 88, 245, 79, 188, 236, 239,
748            79, 140, 153, 111, 5, 197, 172, 89, 177, 36, 24
749        ]
750    );
751
752    assert_eq!(
753        (-&Scalar::one()).to_bytes(),
754        [
755            0, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
756            216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115
757        ]
758    );
759}
760
761#[test]
762fn test_from_bytes() {
763    let mut a = R2;
764
765    for _ in 0..100 {
766        let bytes = a.to_bytes();
767        let b = Scalar::from_bytes(&bytes).unwrap();
768        assert_eq!(a, b);
769
770        // Test negation roundtrip
771        let bytes = (-a).to_bytes();
772        let b = Scalar::from_bytes(&bytes).unwrap();
773        assert_eq!(-a, b);
774
775        a = a.square();
776    }
777}
778
779#[cfg(test)]
780const LARGEST: Scalar = Scalar([
781    0xffff_ffff_0000_0000,
782    0x53bd_a402_fffe_5bfe,
783    0x3339_d808_09a1_d805,
784    0x73ed_a753_299d_7d48,
785]);
786
787#[test]
788fn test_addition() {
789    let mut tmp = LARGEST;
790    tmp += &LARGEST;
791
792    assert_eq!(
793        tmp,
794        Scalar([
795            0xffff_fffe_ffff_ffff,
796            0x53bd_a402_fffe_5bfe,
797            0x3339_d808_09a1_d805,
798            0x73ed_a753_299d_7d48,
799        ])
800    );
801
802    let mut tmp = LARGEST;
803    tmp += &Scalar([1, 0, 0, 0]);
804
805    assert_eq!(tmp, Scalar::zero());
806}
807
808#[test]
809fn test_inversion() {
810    assert!(bool::from(Scalar::zero().invert().is_none()));
811    assert_eq!(Scalar::one().invert().unwrap(), Scalar::one());
812    assert_eq!((-&Scalar::one()).invert().unwrap(), -&Scalar::one());
813
814    let mut tmp = R2;
815
816    for _ in 0..100 {
817        let mut tmp2 = tmp.invert().unwrap();
818        tmp2.mul_assign(&tmp);
819
820        assert_eq!(tmp2, Scalar::one());
821
822        tmp.add_assign(&R2);
823    }
824}
825
826#[test]
827fn test_from_raw() {
828    assert_eq!(
829        Scalar::from_raw([
830            0x0001_ffff_fffd,
831            0x5884_b7fa_0003_4802,
832            0x998c_4fef_ecbc_4ff5,
833            0x1824_b159_acc5_056f,
834        ]),
835        Scalar::from_raw([0xffff_ffff_ffff_ffff; 4])
836    );
837
838    assert_eq!(Scalar::from_raw(MODULUS.0), Scalar::zero());
839
840    assert_eq!(Scalar::from_raw([1, 0, 0, 0]), R);
841}
842
843#[cfg(feature = "zeroize")]
844#[test]
845fn test_zeroize() {
846    use zeroize::Zeroize;
847
848    let mut a = Scalar::from_raw([
849        0x1fff_3231_233f_fffd,
850        0x4884_b7fa_0003_4802,
851        0x998c_4fef_ecbc_4ff3,
852        0x1824_b159_acc5_0562,
853    ]);
854    a.zeroize();
855    // Fixed: disambiguate ct_eq
856    assert!(bool::from(subtle::ConstantTimeEq::ct_eq(&a, &Scalar::zero())));
857}