use alloc::vec::Vec; use core::fmt::{self, Debug, Display, Formatter}; use core::hash::{Hash, Hasher}; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use itertools::Itertools; use num::bigint::BigUint; use num::{Integer, One}; use serde::{Deserialize, Serialize}; use crate::types::{Field, PrimeField, Sample}; /// The base field of the secp256k1 elliptic curve. /// /// Its order is /// ```ignore /// P = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 /// = 115792089237316195423570985008687907852837564279074904382605163141518161494337 /// = 2**256 - 432420386565659656852420866394968145599 /// ``` #[derive(Copy, Clone, Serialize, Deserialize)] pub struct Secp256K1Scalar(pub [u64; 4]); fn biguint_from_array(arr: [u64; 4]) -> BigUint { BigUint::from_slice(&[ arr[0] as u32, (arr[0] >> 32) as u32, arr[1] as u32, (arr[1] >> 32) as u32, arr[2] as u32, (arr[2] >> 32) as u32, arr[3] as u32, (arr[3] >> 32) as u32, ]) } impl Default for Secp256K1Scalar { fn default() -> Self { Self::ZERO } } impl PartialEq for Secp256K1Scalar { fn eq(&self, other: &Self) -> bool { self.to_canonical_biguint() == other.to_canonical_biguint() } } impl Eq for Secp256K1Scalar {} impl Hash for Secp256K1Scalar { fn hash(&self, state: &mut H) { self.to_canonical_biguint().hash(state) } } impl Display for Secp256K1Scalar { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { Display::fmt(&self.to_canonical_biguint(), f) } } impl Debug for Secp256K1Scalar { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { Debug::fmt(&self.to_canonical_biguint(), f) } } impl Sample for Secp256K1Scalar { #[inline] fn sample(rng: &mut R) -> Self where R: rand::RngCore + ?Sized, { use num::bigint::RandBigInt; Self::from_noncanonical_biguint(rng.gen_biguint_below(&Self::order())) } } impl Field for Secp256K1Scalar { const ZERO: Self = Self([0; 4]); const ONE: Self = Self([1, 0, 0, 0]); const TWO: Self = Self([2, 0, 0, 0]); const NEG_ONE: Self = Self([ 0xBFD25E8CD0364140, 0xBAAEDCE6AF48A03B, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, ]); const TWO_ADICITY: usize = 6; const CHARACTERISTIC_TWO_ADICITY: usize = Self::TWO_ADICITY; // Sage: `g = GF(p).multiplicative_generator()` const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([7, 0, 0, 0]); // Sage: `g_2 = power_mod(g, (p - 1) // 2^6), p)` // 5480320495727936603795231718619559942670027629901634955707709633242980176626 const POWER_OF_TWO_GENERATOR: Self = Self([ 0x992f4b5402b052f2, 0x98BDEAB680756045, 0xDF9879A3FBC483A8, 0xC1DC060E7A91986, ]); const BITS: usize = 256; fn order() -> BigUint { BigUint::from_slice(&[ 0xD0364141, 0xBFD25E8C, 0xAF48A03B, 0xBAAEDCE6, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, ]) } fn characteristic() -> BigUint { Self::order() } fn try_inverse(&self) -> Option { if self.is_zero() { return None; } // Fermat's Little Theorem Some(self.exp_biguint(&(Self::order() - BigUint::one() - BigUint::one()))) } fn from_noncanonical_biguint(val: BigUint) -> Self { Self( val.to_u64_digits() .into_iter() .pad_using(4, |_| 0) .collect::>()[..] .try_into() .expect("error converting to u64 array"), ) } #[inline] fn from_canonical_u64(n: u64) -> Self { Self([n, 0, 0, 0]) } #[inline] fn from_noncanonical_u128(n: u128) -> Self { Self([n as u64, (n >> 64) as u64, 0, 0]) } #[inline] fn from_noncanonical_u96(n: (u64, u32)) -> Self { Self([n.0, n.1 as u64, 0, 0]) } fn from_noncanonical_i64(n: i64) -> Self { let f = Self::from_canonical_u64(n.unsigned_abs()); if n < 0 { -f } else { f } } fn from_noncanonical_u64(n: u64) -> Self { Self::from_canonical_u64(n) } } impl PrimeField for Secp256K1Scalar { fn to_canonical_biguint(&self) -> BigUint { let mut result = biguint_from_array(self.0); if result >= Self::order() { result -= Self::order(); } result } } impl Neg for Secp256K1Scalar { type Output = Self; #[inline] fn neg(self) -> Self { if self.is_zero() { Self::ZERO } else { Self::from_noncanonical_biguint(Self::order() - self.to_canonical_biguint()) } } } impl Add for Secp256K1Scalar { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { let mut result = self.to_canonical_biguint() + rhs.to_canonical_biguint(); if result >= Self::order() { result -= Self::order(); } Self::from_noncanonical_biguint(result) } } impl AddAssign for Secp256K1Scalar { #[inline] fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; } } impl Sum for Secp256K1Scalar { fn sum>(iter: I) -> Self { iter.fold(Self::ZERO, |acc, x| acc + x) } } impl Sub for Secp256K1Scalar { type Output = Self; #[inline] #[allow(clippy::suspicious_arithmetic_impl)] fn sub(self, rhs: Self) -> Self { self + -rhs } } impl SubAssign for Secp256K1Scalar { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; } } impl Mul for Secp256K1Scalar { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self::from_noncanonical_biguint( (self.to_canonical_biguint() * rhs.to_canonical_biguint()).mod_floor(&Self::order()), ) } } impl MulAssign for Secp256K1Scalar { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; } } impl Product for Secp256K1Scalar { #[inline] fn product>(iter: I) -> Self { iter.reduce(|acc, x| acc * x).unwrap_or(Self::ONE) } } impl Div for Secp256K1Scalar { type Output = Self; #[allow(clippy::suspicious_arithmetic_impl)] fn div(self, rhs: Self) -> Self::Output { self * rhs.inverse() } } impl DivAssign for Secp256K1Scalar { fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; } } #[cfg(test)] mod tests { use crate::test_field_arithmetic; test_field_arithmetic!(crate::secp256k1_scalar::Secp256K1Scalar); }